From 731ba745caacf179c581bbb1bb4bfbfa204020a1 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sat, 8 Oct 2016 00:56:30 -0500 Subject: [PATCH 001/120] Add, and update, documentation build targets. --- doc/Jamfile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/Jamfile b/doc/Jamfile index d97b9559d2..11cdab7ac1 100644 --- a/doc/Jamfile +++ b/doc/Jamfile @@ -47,3 +47,10 @@ html article : article.rst : html "--link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css" ; + ; + +############################################################################### +alias boostdoc ; +explicit boostdoc ; +alias boostrelease : python tutorial reference article ; +explicit boostrelease ; \ No newline at end of file From 88ea1f96261400a54e9903c490beab623b005986 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 9 Oct 2016 11:04:38 -0500 Subject: [PATCH 002/120] Fix syntax error caused by merging. --- doc/Jamfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/Jamfile b/doc/Jamfile index 11cdab7ac1..a68555adec 100644 --- a/doc/Jamfile +++ b/doc/Jamfile @@ -47,10 +47,9 @@ html article : article.rst : html "--link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css" ; - ; ############################################################################### alias boostdoc ; explicit boostdoc ; alias boostrelease : python tutorial reference article ; -explicit boostrelease ; \ No newline at end of file +explicit boostrelease ; From 60fba03e99a0e04fc946de523b126edb6fdda048 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 3 Mar 2017 22:28:22 -0600 Subject: [PATCH 003/120] 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 aedeed67ea..4a766ac24a 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 44ea0562b2ba45202c750c22b7ece98dafbbb8b4 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 5 Mar 2017 08:56:57 -0600 Subject: [PATCH 004/120] 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 4a766ac24a..f585953d00 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 07b1489f3bad91a0edd1a98d8923287f8e61ce0e Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 5 Mar 2017 15:16:36 -0600 Subject: [PATCH 005/120] 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 f585953d00..8c37ec6d37 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 5e4b44e0af2489a5a5c370f468a6a7722232b908 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Mon, 6 Mar 2017 10:30:41 -0600 Subject: [PATCH 006/120] 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 8c37ec6d37..f14dc1131a 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 8c2a808cbed444c2e17017ed8045ff2579fefb08 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Mon, 31 Jul 2017 11:37:52 -0400 Subject: [PATCH 007/120] 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 4ccb0d3879..0000000000 --- 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 80ce257ce4..c57b02d03d 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 32e3363f44..19dbe4d97e 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 39edfd45cfe79b2ce9609a17fedba6e110faa62a Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 13 Aug 2017 20:44:52 -0400 Subject: [PATCH 008/120] 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 eb7fca2865..90e56f0c1d 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 fed4f0d0f97be42da4f2505953a92b2cebdd14ec Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 13 Aug 2017 20:45:13 -0400 Subject: [PATCH 009/120] Fix version number. --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 6edd7cd48d..848172f957 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 a383ecdd88a9ad9b96d3f993fcf44bdcdcb1f638 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 15 Mar 2018 15:29:06 -0400 Subject: [PATCH 010/120] Fix build warning. --- Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jamfile b/Jamfile index 3a35dde048..32e87d80f1 100644 --- a/Jamfile +++ b/Jamfile @@ -46,7 +46,7 @@ rule version-suffix ( version ) python-id = [ option.get "python-buildid" ] ; if $(python-id) { - PYTHON_ID = [ regex.replace $(python-id) [*\\/:.\"\'] _ ] ; + PYTHON_ID = [ regex.replace $(python-id) "[*\\/:.\"\']" _ ] ; } rule python-tag ( name : type ? : property-set ) From 4f6d547c0af4c400dc5d059ccd847426ff21852f Mon Sep 17 00:00:00 2001 From: Orivej Desh Date: Wed, 13 Feb 2019 18:33:11 +0000 Subject: [PATCH 011/120] clear python exception after expected attribute lookup failure Python 3.7.0 asserts that attribute lookup functions are called without outstanding exceptions: https://github.com/python/cpython/blob/v3.7.0a2/Objects/typeobject.c#L3037 Motivation: https://bugs.python.org/issue34068#msg321262 Therefore the error set by the first PyObject_GetItem should be cleared before calling PyObject_GetAttrString. --- src/object/function.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/object/function.cpp b/src/object/function.cpp index e612963b17..9d4745d102 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -444,7 +444,9 @@ void function::add_to_namespace( if (dict == 0) throw_error_already_set(); + assert(!PyErr_Occurred()); handle<> existing(allow_null(::PyObject_GetItem(dict.get(), name.ptr()))); + PyErr_Clear(); if (existing) { @@ -485,16 +487,15 @@ void function::add_to_namespace( if (new_func->name().is_none()) new_func->m_name = name; + assert(!PyErr_Occurred()); handle<> name_space_name( allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast("__name__")))); + PyErr_Clear(); if (name_space_name) new_func->m_namespace = object(name_space_name); } - // The PyObject_GetAttrString() or PyObject_GetItem calls above may - // have left an active error - PyErr_Clear(); if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) throw_error_already_set(); From 65bfec2d97acd2e9b051b52ce6dcd6f8282fb1b5 Mon Sep 17 00:00:00 2001 From: SPKorhonen Date: Mon, 4 Mar 2019 04:59:48 +0200 Subject: [PATCH 012/120] Fix static object initialization under Visual Studio 2017 (#208) Fix static object initialization under VS 15.7.2 --- include/boost/python/detail/caller.hpp | 31 ++++++++++++++++++-------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/include/boost/python/detail/caller.hpp b/include/boost/python/detail/caller.hpp index 1bd30bfb5a..557359f5f5 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -109,6 +109,23 @@ struct converter_target_type return 0; } }; + +// Generation of ret moved from caller_arity::impl::signature to here due to "feature" in MSVC 15.7.2 with /O2 +// which left the ret uninitialized and caused segfaults in Python interpreter. +template const signature_element* get_ret() +{ + typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type::type rtype; + typedef typename select_result_converter::type result_converter; + + static const signature_element ret = { + (is_void::value ? "void" : type_id().name()) + , &detail::converter_target_type::get_pytype + , boost::detail::indirect_traits::is_reference_to_non_const::value + }; + + return &ret; +}; + #endif @@ -229,16 +246,12 @@ struct caller_arity { const signature_element * sig = detail::signature::elements(); #ifndef BOOST_PYTHON_NO_PY_SIGNATURES + // MSVC 15.7.2, when compiling to /O2 left the static const signature_element ret, + // originally defined here, uninitialized. This in turn led to SegFault in Python interpreter. + // Issue is resolved by moving the generation of ret to separate function in detail namespace (see above). + const signature_element * ret = detail::get_ret(); - typedef BOOST_DEDUCED_TYPENAME Policies::template extract_return_type::type rtype; - typedef typename select_result_converter::type result_converter; - - static const signature_element ret = { - (is_void::value ? "void" : type_id().name()) - , &detail::converter_target_type::get_pytype - , boost::detail::indirect_traits::is_reference_to_non_const::value - }; - py_func_sig_info res = {sig, &ret }; + py_func_sig_info res = {sig, ret }; #else py_func_sig_info res = {sig, sig }; #endif From 4b01139720128d45e6887b78271baf4eb201e24d Mon Sep 17 00:00:00 2001 From: Tom Kent Date: Sun, 3 Mar 2019 21:02:57 -0600 Subject: [PATCH 013/120] Ssize t warning - trac #3353 (#21) Fixes msvc unsafe type conversion warning - trac num: 3353 --- include/boost/python/list.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/list.hpp b/include/boost/python/list.hpp index 10fd40fda5..0d5e2c8fd9 100644 --- a/include/boost/python/list.hpp +++ b/include/boost/python/list.hpp @@ -73,7 +73,7 @@ class list : public detail::list_base } template - long count(T const& value) const + ssize_t count(T const& value) const { return base::count(object(value)); } From 6bd6d7185026adbdbe398cb6ba162be9e42b9913 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Mon, 18 Mar 2019 20:00:59 +0300 Subject: [PATCH 014/120] Fix -Wregister error on Clang in C++17 mode Suppresses the warning on GCC, Clang, and MSVC. --- include/boost/python/detail/wrap_python.hpp | 26 +++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 9fdb222c68..481baa7842 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -145,12 +145,38 @@ typedef int pid_t; #endif // _WIN32 +#if defined(__GNUC__) +# if defined(__has_warning) +# define BOOST_PYTHON_GCC_HAS_WREGISTER __has_warning("-Wregister") +# else +# define BOOST_PYTHON_GCC_HAS_WREGISTER __GNUC__ >= 7 +# endif +#else +# define BOOST_PYTHON_GCC_HAS_WREGISTER 0 +#endif + +// Python.h header uses `register` keyword until Python 3.4 +#if BOOST_PYTHON_GCC_HAS_WREGISTER +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wregister" +#elif defined(_MSC_VER) +# pragma warning(push) +# pragma warning(disable : 5033) // 'register' is no longer a supported storage class +#endif + #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 2 && PY_MICRO_VERSION < 2 # include #else # include #endif +#if BOOST_PYTHON_GCC_HAS_WREGISTER +# pragma GCC diagnostic pop +#elif defined(_MSC_VER) +# pragma warning(pop) +#endif +#undef BOOST_PYTHON_GCC_HAS_WREGISTER + #ifdef BOOST_PYTHON_ULONG_MAX_UNDEFINED # undef ULONG_MAX # undef BOOST_PYTHON_ULONG_MAX_UNDEFINED From 1f1b9b6aefd2a9464d335a627f94ebf6a9e4ebf9 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Sat, 23 Mar 2019 01:47:38 +0300 Subject: [PATCH 015/120] Fix hypot issue on MinGW --- include/boost/python/detail/wrap_python.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 481baa7842..c0748ddf00 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -83,6 +83,13 @@ // than MSVC on Win32 // #if defined(_WIN32) || defined(__CYGWIN__) + +// Python.h defines a macro with hypot name, what breaks libstdc++ math header +// that it tries to include afterwards. +# if defined(__MINGW32__) +# include +# endif + # if defined(__GNUC__) && defined(__CYGWIN__) # if defined(__LP64__) From 72e254bf8b9ab847343bfbc85b31e723ebb66309 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 28 Sep 2018 09:30:33 +0100 Subject: [PATCH 016/120] Fix name of file in tutorial I think it's meant to refer to the Jamroot file being discussed, not Jamrules. --- doc/tutorial.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index 71d2585089..d7c0cfa93e 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -121,7 +121,7 @@ __jam__ file. Simply copy the file and tweak [^use-project boost] to where your boost root directory is and you're OK. -The comments contained in the Jamrules file above should be sufficient +The comments contained in the Jamroot file above should be sufficient to get you going. [h2 Running bjam] From 0d0cd711a764a3b32d2cd19a1049eb9f36b4fd06 Mon Sep 17 00:00:00 2001 From: Owens Date: Fri, 17 Aug 2018 06:06:03 +1000 Subject: [PATCH 017/120] Enable forward declaration of unwind_type() in msvc14.15 and later. Name lookup in msvc has changed between 14.14 and 14.15 making it consistent with other compilers. Forward declaration of unwind_type() is now required as it is for other compilers. Resolves compilation errors identified in: https://github.com/boostorg/python/issues/228 --- include/boost/python/detail/unwind_type.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/boost/python/detail/unwind_type.hpp b/include/boost/python/detail/unwind_type.hpp index f6cdab64fe..b81bf7c898 100644 --- a/include/boost/python/detail/unwind_type.hpp +++ b/include/boost/python/detail/unwind_type.hpp @@ -11,13 +11,15 @@ namespace boost { namespace python { namespace detail { -#ifndef _MSC_VER //if forward declared, msvc6.5 does not recognize them as inline -// forward declaration, required (at least) by Tru64 cxx V6.5-042 +#if (!defined(_MSC_VER) || _MSC_VER >= 1915) +// If forward declared, msvc6.5 does not recognize them as inline. +// However, as of msvc14.15 (_MSC_VER 1915/Visual Studio 15.8.0) name lookup is now consistent with other compilers. +// forward declaration, required (at least) by Tru64 cxx V6.5-042 and msvc14.15 template inline typename Generator::result_type unwind_type(U const& p, Generator* = 0); -// forward declaration, required (at least) by Tru64 cxx V6.5-042 +// forward declaration, required (at least) by Tru64 cxx V6.5-042 and msvc14.15 template inline typename Generator::result_type unwind_type(boost::type*p = 0, Generator* = 0); @@ -83,7 +85,7 @@ struct unwind_helper template inline typename Generator::result_type -#ifndef _MSC_VER +#if (!defined(_MSC_VER) || _MSC_VER >= 1915) unwind_type(U const& p, Generator*) #else unwind_type(U const& p, Generator* = 0) @@ -148,7 +150,7 @@ struct unwind_helper2 // why bother? template inline typename Generator::result_type -#ifndef _MSC_VER +#if (!defined(_MSC_VER) || _MSC_VER >= 1915) unwind_type(boost::type*, Generator*) #else unwind_type(boost::type*p =0, Generator* =0) From 0b0c0536d6f367768152a91799e7ea1eb02f91c6 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Tue, 26 Mar 2019 21:02:08 +0300 Subject: [PATCH 018/120] The right hypot fix for MinGW --- include/boost/python/detail/wrap_python.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index c0748ddf00..13679dbb8f 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -47,6 +47,13 @@ # endif #endif +// pyconfig.h defines a macro with hypot name, what breaks libstdc++ math headers +// that Python.h tries to include afterwards. +#if defined(__MINGW32__) +# include +# include +#endif + # include # if defined(_SGI_COMPILER_VERSION) && _SGI_COMPILER_VERSION >= 740 # undef _POSIX_C_SOURCE @@ -84,12 +91,6 @@ // #if defined(_WIN32) || defined(__CYGWIN__) -// Python.h defines a macro with hypot name, what breaks libstdc++ math header -// that it tries to include afterwards. -# if defined(__MINGW32__) -# include -# endif - # if defined(__GNUC__) && defined(__CYGWIN__) # if defined(__LP64__) From fdc9ec760ff3ddd9ab90b4b46f4edf3a8e4aa7bc Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Sat, 30 Mar 2019 17:42:34 +0300 Subject: [PATCH 019/120] Fixed module tests fail Since recently lightweight_test introduced a sanitation to ensure that `boost::report_errors()` is called, and it does not in module tests. The problem could be fixed by exporting the function and calling it from these python tests, but as it already done in other module tests I just turned those usages lightweight_test to a regular assertation. --- test/test_class.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/test_class.hpp b/test/test_class.hpp index 5404fdba27..a9324e9c47 100644 --- a/test/test_class.hpp +++ b/test/test_class.hpp @@ -4,17 +4,17 @@ // http://www.boost.org/LICENSE_1_0.txt) #ifndef TEST_CLASS_DWA2002326_HPP # define TEST_CLASS_DWA2002326_HPP -# include +# include template 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; } + virtual ~test_class() { BOOST_ASSERT(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; } + void set(int _x) { BOOST_ASSERT(magic == 7654321 + n); this->x = _x; } + int value() const { BOOST_ASSERT(magic == 7654321 + n); return x; } operator int() const { return x; } static int count() { return counter; } From 8c8b0dc2152efb2706a782ff1c0fdd2e0705ce69 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Thu, 18 Apr 2019 00:02:52 +0300 Subject: [PATCH 020/120] Only boost-install boost_numpy when it's being built --- build/Jamfile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/build/Jamfile b/build/Jamfile index 34f99dde73..d03d4dd084 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -30,8 +30,6 @@ else ; } -if [ python.configured ] -{ project boost/python : source-location ../src ; @@ -123,7 +121,7 @@ lib boost_numpy boost_python on:BOOST_DEBUG_PYTHON -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @$(__name__).python-tag + @$(__name__).python-tag @python.require-py : # default build @@ -142,8 +140,16 @@ lib boost_numpy # `install` installs the two libraries and their dependencies and is similar # to issuing `b2 --with-python install` from top level -boost-install boost_python boost_numpy ; - +if [ python.configured ] +{ + if [ python.numpy ] + { + boost-install boost_python boost_numpy ; + } + else + { + boost-install boost_python ; + } } else { From 1727b67a5a92c8c3564d4ee244fffd758e54d7cc Mon Sep 17 00:00:00 2001 From: Julien Schueller Date: Sat, 1 Jun 2019 11:07:30 +0200 Subject: [PATCH 021/120] detail/caller.hpp:127:2: error: extra ';' [-Wpedantic] --- 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 557359f5f5..2834d6da99 100644 --- a/include/boost/python/detail/caller.hpp +++ b/include/boost/python/detail/caller.hpp @@ -124,7 +124,7 @@ template const signature_element* get_ret() }; return &ret; -}; +} #endif From 15115eb1f844e9ac8ed5dd454d46a4e7b5ae5b48 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 19 Mar 2020 17:47:06 -0400 Subject: [PATCH 022/120] Fix appveyor build failures. --- .appveyor.yml | 60 ++++++++++++++++++++++++++++---------------------- .travis.yml | 35 ++++++++++++----------------- fabscript | 6 ++--- test/fabscript | 4 ++-- 4 files changed, 53 insertions(+), 52 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 05d2480dd9..c8205eaeb1 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -4,7 +4,6 @@ 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_66_0 matrix: @@ -12,24 +11,28 @@ environment: # a later point release. # See: http://www.appveyor.com/docs/installed-software#python - - PYTHON: "C:\\Python27" - PYTHON_VERSION: "2.7.x" # currently 2.7.9 - PYTHON_ARCH: "32" - MSVC: "14.0" - ARCH: x86 - - - PYTHON: "C:\\Python36-x64" - PYTHON_VERSION: "3.6.x" - PYTHON_ARCH: "64" - MSVC: "12.0" + - PYTHON: C:\\Python36-x64 + PYTHON_VERSION: 3.6.x + PYTHON_ARCH: 64 + MSVC: 12.0 ARCH: x86_64 + BOOST_PREFIX: C:\Libraries\boost_1_66_0 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - PYTHON: "C:\\Python36-x64" - PYTHON_VERSION: "3.6.x" - PYTHON_ARCH: "64" - MSVC: "14.13.26128" + PYTHON: C:\\Python36-x64 + PYTHON_VERSION: 3.6.x + PYTHON_ARCH: 64 + MSVC: 15.9.19 + ARCH: x86_64 + BOOST_PREFIX: C:\Libraries\boost_1_69_0 + + - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 + PYTHON: C:\\Python36-x64 + PYTHON_VERSION: 3.6.x + PYTHON_ARCH: 64 + MSVC: 16.6.5 ARCH: x86_64 + BOOST_PREFIX: C:\Libraries\boost_1_73_0 install: # If there is a newer build queued for the same PR, cancel this one. @@ -64,28 +67,33 @@ install: # Upgrade to the latest version of pip to avoid it displaying warnings # about it being out of date. - - "pip install --disable-pip-version-check --user --upgrade pip" + - "python -m pip install --disable-pip-version-check --user --upgrade pip" # Install the build dependencies of the project. If some dependencies contain # 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 - - | - curl -LfsS -o faber.tar.gz https://github.com/stefanseefeld/faber/archive/snapshot/2018-04-08.tar.gz - tar xf faber.tar.gz - CD faber-snapshot-2018-04-08 - python setup.py install - CD .. + + - curl -LfsS -o vswhere.exe https://github.com/Microsoft/vswhere/releases/download/2.8.4/vswhere.exe + #- | + # curl -LfsS -o faber.tar.gz https://github.com/stefanseefeld/faber/archive/snapshot/2020-08-01.tar.gz + # tar xf faber.tar.gz + # CD faber-snapshot-2020-08-01 + # python setup.py install + # CD .. + - python -m pip install faber # report the available MSVC compilers - - faber --info=tools cxx + - faber --log=tools --info=tools cxx - easy_install sphinx - - pip install numpy + - python -m pip install numpy + - set FARGS=--log=summary --log=output --log=actions --log=commands --with-boost-include=%BOOST_PREFIX% target.arch=%ARCH% cxx.name=msvc cxx.version=%MSVC% build_script: - - faber --with-boost-include=%BOOST_PREFIX% target.arch=%ARCH% msvc.version=%MSVC% + - faber %FARGS% config || type config.log + - faber %FARGS% -j8 test_script: - - faber --with-boost-include=%BOOST_PREFIX% test.report target.arch=%ARCH% msvc.version=%MSVC% + - faber %FARGS% -j8 test.report after_test: # If tests are successful, create binary packages for the project. diff --git a/.travis.yml b/.travis.yml index 5d37070b1e..ef7828c60a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -sudo: required -dist: trusty +dist: bionic language: cpp @@ -15,7 +14,7 @@ env: global: - secure: BRNUkxN3p8f+uYKWC3Hr0VPqZA0PxbWr1DJlcI4hbiZtzKhMCWjDmd9UW9CzzexqeOxpd+9s0G87qvOur+wMSVxugDxtTesZrh1czXHeSVxgQrYD783XJtQJ9aYypbChkiboRD6Xpmbq7itwMuHBJMFtCuDxMynpU1jWwkyTf2Y= -matrix: +jobs: include: - os: linux env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++98 @@ -40,9 +39,10 @@ addons: sources: - ubuntu-toolchain-r-test packages: - - gcc-4.8 - - g++-4.8 + - gcc + - g++ - clang + - python3-pip - python-numpy - python-sphinx - python3-dev @@ -57,12 +57,6 @@ cache: directories: - $HOME/Boost -before_install: - # The Trusty image has several Python versions pre-installed compiled with - # conflicting UCS2 and UCS4 unicode. Modify the PATH to skip the TravisCI python. - # See https://github.com/travis-ci/travis-ci/issues/4948 for details. - - export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g") - install: # Install our own version of Boost (the subset we need) as the system version is # too old (for C++11 support). @@ -83,15 +77,14 @@ install: echo "using cached Boost prerequisites." fi # Install Faber, the build tool. - date=2018-04-08 - wget https://github.com/stefanseefeld/faber/archive/snapshot/$date.tar.gz - tar xf $date.tar.gz - pushd faber-snapshot-$date - #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 + python3 -m pip install setuptools + python3 -m pip install faber + #date=2020-08-01 + #wget https://github.com/stefanseefeld/faber/archive/snapshot/$date.tar.gz + #tar xf $date.tar.gz + #pushd faber-snapshot-$date + #sudo python3 setup.py install + #popd before_script: - sed -e "s/\$PYTHON/$PYTHON/g" .ci/faber > ~/.faber @@ -104,7 +97,7 @@ script: if [ "$DOC" ]; then BOOST_ROOT=$HOME/Boost faber --builddir=build doc.html else - faber --with-boost-include=$HOME/Boost --builddir=build test.report cxx.name=$CXX cxxflags=$CXXFLAGS + faber --with-boost-include=$HOME/Boost --builddir=build test.report cxx.name=$CXX cxxflags=$CXXFLAGS -j8 fi after_success: diff --git a/fabscript b/fabscript index 054ed90e56..8188779fd3 100644 --- a/fabscript +++ b/fabscript @@ -75,8 +75,8 @@ 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) -doc = module('doc', features=config.use) +src = module('src', features=features|config.use) +test = module('test', features=features|config.use) +doc = module('doc', features=features|config.use) default = src.default diff --git a/test/fabscript b/test/fabscript index 1989cc0d13..61a5a1ca7d 100644 --- a/test/fabscript +++ b/test/fabscript @@ -123,9 +123,9 @@ tests.append(extension_test('auto_ptr', import_ = binary('import_', ['import_.cpp', src.bpl], features=features|python_libs) if platform.os == 'Windows': command = """set PATH=$(runpath);%PATH% -$(>[1]) $(>[2])""" +$(>[0]) $(>[1])""" else: - command = 'LD_LIBRARY_PATH=$(runpath) $(>[1]) $(>[2])' + command = 'LD_LIBRARY_PATH=$(runpath) $(>[0]) $(>[1])' tests.append(test('import', [import_, 'import_.py'], run=action('run', command), From 17886fc2960d8e69eaa6f20f1d5c93a5477d1719 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Tue, 31 Mar 2020 16:11:07 -0400 Subject: [PATCH 023/120] Change __BORLANDC__ to BOOST_BORLANDC, which is defined in Boost config for the Embarcadero non-clang-based compilers. --- include/boost/python/def_visitor.hpp | 4 ++-- include/boost/python/detail/msvc_typeinfo.hpp | 2 +- include/boost/python/detail/wrap_python.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/python/def_visitor.hpp b/include/boost/python/def_visitor.hpp index 9c8907cd6f..18dd928684 100644 --- a/include/boost/python/def_visitor.hpp +++ b/include/boost/python/def_visitor.hpp @@ -16,7 +16,7 @@ template class class_; class def_visitor_access { # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ - || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. public: @@ -52,7 +52,7 @@ class def_visitor friend class def_visitor_access; # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \ - || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + || BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x551)) // Tasteless as this may seem, making all members public allows member templates // to work in the absence of member template friends. public: diff --git a/include/boost/python/detail/msvc_typeinfo.hpp b/include/boost/python/detail/msvc_typeinfo.hpp index bfc84164f0..2c5f6e572d 100644 --- a/include/boost/python/detail/msvc_typeinfo.hpp +++ b/include/boost/python/detail/msvc_typeinfo.hpp @@ -47,7 +47,7 @@ inline typeinfo typeid_ref(type*, ...) return detail::typeid_ref_1((T(*)())0); } -#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)) +#if defined(BOOST_MSVC) || (defined(BOOST_BORLANDC) && !defined(BOOST_DISABLE_WIN32)) # define BOOST_PYTT_DECL __cdecl #else # define BOOST_PYTT_DECL /**/ diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 13679dbb8f..9d5f5422a2 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -146,7 +146,7 @@ typedef int pid_t; # undef hypot // undo the evil #define left by Python. -# elif defined(__BORLANDC__) +# elif defined(__BORLANDC__) && !defined(__clang__) # undef HAVE_HYPOT # define HAVE_HYPOT 1 # endif From 5e2d55d801632fc8ecaf12840382962cb6480931 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Sun, 19 Apr 2020 16:25:56 -0400 Subject: [PATCH 024/120] Revert back to original, as __cdecl is fine with the Embarcadero C++ clang-based compilers. --- include/boost/python/detail/msvc_typeinfo.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/detail/msvc_typeinfo.hpp b/include/boost/python/detail/msvc_typeinfo.hpp index 2c5f6e572d..bfc84164f0 100644 --- a/include/boost/python/detail/msvc_typeinfo.hpp +++ b/include/boost/python/detail/msvc_typeinfo.hpp @@ -47,7 +47,7 @@ inline typeinfo typeid_ref(type*, ...) return detail::typeid_ref_1((T(*)())0); } -#if defined(BOOST_MSVC) || (defined(BOOST_BORLANDC) && !defined(BOOST_DISABLE_WIN32)) +#if defined(BOOST_MSVC) || (defined(__BORLANDC__) && !defined(BOOST_DISABLE_WIN32)) # define BOOST_PYTT_DECL __cdecl #else # define BOOST_PYTT_DECL /**/ From 01ab5105851b1d59c0f8012dbeea07a0500e0f65 Mon Sep 17 00:00:00 2001 From: Andrey Semashev Date: Mon, 11 May 2020 19:36:44 +0300 Subject: [PATCH 025/120] Removed usage of deprecated header boost/detail/iterator.hpp. The header is deprecated in favor of . It generates compiler warnings and will be removed in a future release. --- include/boost/python/object/iterator.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/object/iterator.hpp b/include/boost/python/object/iterator.hpp index e2f65721fb..874950365d 100644 --- a/include/boost/python/object/iterator.hpp +++ b/include/boost/python/object/iterator.hpp @@ -25,7 +25,7 @@ # include -# include +# include namespace boost { namespace python { namespace objects { @@ -42,7 +42,7 @@ struct iterator_range { iterator_range(object sequence, Iterator start, Iterator finish); - typedef boost::detail::iterator_traits traits_t; + typedef std::iterator_traits traits_t; struct next { From bf824c1b98d1d523f4239063b073afdf086fa741 Mon Sep 17 00:00:00 2001 From: Tyler Kieft Date: Thu, 19 Mar 2020 16:21:15 -0400 Subject: [PATCH 026/120] Ensure all doctests run --- test/args.py | 27 +++++++++++++++++---------- test/dict.cpp | 14 +++++++------- test/dict.py | 7 ++++--- test/fabscript | 28 ++++++++++++++-------------- test/iterator.py | 10 ++++++---- test/list.py | 9 +++++---- test/long.py | 7 ++++--- test/map_indexing_suite.py | 23 +++++++++-------------- test/object.py | 13 +++++++------ test/pickle2.py | 5 +++-- test/pickle3.py | 5 +++-- test/str.py | 7 ++++--- test/test_builtin_converters.py | 9 ++------- test/tuple.py | 5 +++-- 14 files changed, 88 insertions(+), 81 deletions(-) diff --git a/test/args.py b/test/args.py index e884c06bea..5d89921467 100644 --- a/test/args.py +++ b/test/args.py @@ -1,15 +1,19 @@ # 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}) +>>> args, kwargs = raw(3, 4, foo = 'bar', baz = 42) +>>> args +(3, 4) +>>> kwargs['foo'] +'bar' +>>> kwargs['baz'] +42 Prove that we can handle empty keywords and non-keywords - + >>> raw(3, 4) ((3, 4), {}) @@ -76,7 +80,7 @@ ... 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) @@ -123,10 +127,16 @@ 1 >>> y = Y(value = 33) ->>> y.raw(this = 1, that = 'the other')[1] -{'this': 1, 'that': 'the other'} +>>> _, kwargs = y.raw(this = 1, that = 'the other') +>>> kwargs['this'] +1 +>>> kwargs['that'] +'the other' """ + +from __future__ import print_function + def run(args = None): import sys import doctest @@ -143,6 +153,3 @@ def run(args = None): import args_ext help(args_ext) sys.exit(status) - - - diff --git a/test/dict.cpp b/test/dict.cpp index 375905d69a..4f3490a421 100644 --- a/test/dict.cpp +++ b/test/dict.cpp @@ -21,11 +21,13 @@ object new_dict() object data_dict() { dict tmp1; - tmp1["key1"] = "value1"; dict tmp2; tmp2["key2"] = "value2"; tmp1[1] = tmp2; + + tmp1["key1"] = "value1"; + return tmp1; } @@ -60,22 +62,20 @@ void work_with_dict(dict data1, dict 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)); + tmp[1] = "a test string"; + print(tmp.get(1)); 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); diff --git a/test/dict.py b/test/dict.py index 72c37d99e1..9b1149ae60 100644 --- a/test/dict.py +++ b/test/dict.py @@ -1,7 +1,6 @@ # 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): @@ -22,14 +21,16 @@ >>> 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 +a test string None {1.5: 13, 1: 'a test string'} default default """ +from __future__ import print_function + def run(args = None): import sys import doctest @@ -37,7 +38,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/fabscript b/test/fabscript index 61a5a1ca7d..03e4c6f919 100644 --- a/test/fabscript +++ b/test/fabscript @@ -21,14 +21,14 @@ src = module('..src') python_libs=python.instance().libs features |= runpath(src.bpl.path, base='') -def extension_test(name, ext=[], script=None, np=False, +def extension_test(name, exts=[], script=None, numpy=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. + * exts: 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 + * numpy: if true, add boost_numpy to sources * features: pre-defined features * condition: any condition under which to run the test Return: @@ -36,17 +36,17 @@ def extension_test(name, ext=[], script=None, np=False, 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'] + libs = [src.bnl, src.bpl] if numpy else [src.bpl] + for ext in exts or [name]: + if type(ext) is str: # build from a single source file + ext_name = ext if ext != name else ext + '_ext' + sources = [ext + '.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) + ext_name = ext[0] if ext[0] != name else ext[0] + '_ext' + sources = [source + '.cpp' for source in ext] + ext = extension(ext_name, sources + libs, features=features) + features |= pythonpath(ext.path, base='') + extensions.append(ext) if not script: script = name+'.py' return test(name, script, run=python.run, dependencies=extensions, @@ -167,7 +167,7 @@ for t in ['numpy/dtype', 'numpy/ndarray', 'numpy/indexing', 'numpy/shapes']: - tests.append(extension_test(t, np=True, + tests.append(extension_test(t, numpy=True, condition=set.define.contains('HAS_NUMPY'))) default = report('report', tests, fail_on_failures=True) diff --git a/test/iterator.py b/test/iterator.py index 314a356767..0d75100a09 100644 --- a/test/iterator.py +++ b/test/iterator.py @@ -1,7 +1,6 @@ # 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 * @@ -25,7 +24,7 @@ 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) @@ -56,12 +55,15 @@ >>> ll.push_back(x) >>> for a in ll: #doctest: +NORMALIZE_WHITESPACE ... for b in a: -... print(b, end='') +... print(b, end=' ') ... print('') ... 1 3 5 1 3 5 7 ''' + +from __future__ import print_function + def run(args = None): import sys import doctest @@ -69,7 +71,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/list.py b/test/list.py index 913032db8a..f6cf87096f 100644 --- a/test/list.py +++ b/test/list.py @@ -1,7 +1,6 @@ # 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 * @@ -41,7 +40,7 @@ ['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') @@ -51,7 +50,7 @@ ['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) @@ -103,6 +102,8 @@ ['y', 'x', 'o', 'l', 'l', 'h', 'e', '.'] ''' +from __future__ import print_function + def run(args = None): import sys import doctest @@ -110,7 +111,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/long.py b/test/long.py index f63923632e..157dc57aa9 100644 --- a/test/long.py +++ b/test/long.py @@ -1,9 +1,6 @@ # 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()) @@ -20,6 +17,10 @@ >>> x = Y(long(4294967295)) ''' +import sys +if (sys.version_info.major >= 3): + long = int + def run(args = None): import sys import doctest diff --git a/test/map_indexing_suite.py b/test/map_indexing_suite.py index a5750a833f..e772bb53f9 100644 --- a/test/map_indexing_suite.py +++ b/test/map_indexing_suite.py @@ -1,7 +1,6 @@ # 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 ''' ##################################################################### @@ -25,7 +24,7 @@ # test that a string is implicitly convertible # to an X ->>> x_value('bochi bochi') +>>> x_value('bochi bochi') 'gotya bochi bochi' ##################################################################### @@ -33,9 +32,9 @@ ##################################################################### >>> def print_xmap(xmap): ... s = '[ ' -... for x in xmap: +... for x in xmap: ... s += repr(x) -... s += ' ' +... s += ' ' ... s += ']' ... print(s) @@ -135,7 +134,7 @@ >>> assert not 12345 in xm ##################################################################### -# Some references to the container elements +# Some references to the container elements ##################################################################### >>> z0 = xm['joel'] @@ -156,7 +155,7 @@ kiwi ##################################################################### -# Delete some container element +# Delete some container element ##################################################################### >>> del xm['tenji'] @@ -168,7 +167,7 @@ [ (joel, apple) (kim, kiwi) (mariel, grape) ] ##################################################################### -# Show that the references are still valid +# Show that the references are still valid ##################################################################### >>> z0 # proxy apple @@ -199,7 +198,7 @@ >>> print_xmap(tm) [ (joel, aaa) (kimpo, bbb) ] >>> for el in tm: #doctest: +NORMALIZE_WHITESPACE -... print(el.key(), end='') +... print(el.key(), end=' ') ... dom = el.data() joel kimpo @@ -216,11 +215,12 @@ 4 ##################################################################### -# END.... +# END.... ##################################################################### ''' +from __future__ import print_function def run(args = None): import sys @@ -236,8 +236,3 @@ def run(args = None): status = run()[0] if (status == 0): print("Done.") sys.exit(status) - - - - - diff --git a/test/object.py b/test/object.py index 67a46d9362..cf6c2de0c5 100644 --- a/test/object.py +++ b/test/object.py @@ -1,7 +1,6 @@ # 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 * @@ -130,14 +129,14 @@ 1 Slices - + >>> assert check_string_slice() Operators ->>> def print_args(*args, **kwds): +>>> def print_args(*args, **kwds): ... print(args, kwds) ->>> test_call(print_args, (0, 1, 2, 3), {'a':'A'}) +>>> test_call(print_args, (0, 1, 2, 3), {'a':'A'}) (0, 1, 2, 3) {'a': 'A'} @@ -149,7 +148,7 @@ Now make sure that object is actually managing reference counts - + >>> import weakref >>> class Z: pass ... @@ -164,6 +163,8 @@ death ''' +from __future__ import print_function + def run(args = None): import sys import doctest @@ -171,7 +172,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/pickle2.py b/test/pickle2.py index f4788d3b89..4c11ef3a85 100644 --- a/test/pickle2.py +++ b/test/pickle2.py @@ -1,7 +1,6 @@ # 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__ @@ -35,6 +34,8 @@ Incomplete pickle support (__getstate_manages_dict__ not set) ''' +from __future__ import print_function + def run(args = None): import sys import doctest @@ -42,7 +43,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/pickle3.py b/test/pickle3.py index 932e30f3cd..391e3d00f1 100644 --- a/test/pickle3.py +++ b/test/pickle3.py @@ -1,7 +1,6 @@ # 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__ @@ -30,6 +29,8 @@ Hello from California! 0 84 yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy 126.0 ''' +from __future__ import print_function + def run(args = None): import sys import doctest @@ -37,7 +38,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/str.py b/test/str.py index 4eba0e8769..bfb4994959 100644 --- a/test/str.py +++ b/test/str.py @@ -1,11 +1,10 @@ # 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='') +... for x in args: print(x, end=' ') ... print('') ... >>> work_with_string(printer) #doctest: +NORMALIZE_WHITESPACE @@ -38,6 +37,8 @@ aaaaaaaaaaaaaaaaaaaaa """ +from __future__ import print_function + def run(args = None): import sys import doctest @@ -45,7 +46,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys diff --git a/test/test_builtin_converters.py b/test/test_builtin_converters.py index e612ed23df..0f1b4ded75 100644 --- a/test/test_builtin_converters.py +++ b/test/test_builtin_converters.py @@ -1,9 +1,7 @@ +# -*- coding: utf-8 -*- # 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 * @@ -17,7 +15,7 @@ # Wrappers to simplify tests >>> def should_pass(method, values): -... result = map(method, values[0]) +... result = list(map(method, values[0])) ... if result != values[0]: ... print("Got %s but expected %s" % (result, values[0])) >>> def test_overflow(method, values): @@ -136,9 +134,6 @@ >>> 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?')) diff --git a/test/tuple.py b/test/tuple.py index 1aec5fded4..e2cd5eb179 100644 --- a/test/tuple.py +++ b/test/tuple.py @@ -1,7 +1,6 @@ # 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): @@ -22,6 +21,8 @@ ('hello', 42) """ +from __future__ import print_function + def run(args = None): import sys import doctest @@ -29,7 +30,7 @@ def run(args = None): if args is not None: sys.argv = args return doctest.testmod(sys.modules.get(__name__)) - + if __name__ == '__main__': print("running...") import sys From 9e1132f4f58c45e79365d9ad1ca8e7b9ea981dc4 Mon Sep 17 00:00:00 2001 From: Austin Maliszewski Date: Tue, 28 Jan 2020 17:33:53 -0600 Subject: [PATCH 027/120] Handle NULL from call to PyLong_Type PyLong_Type raises an exception if the argument is not convertible to long, therefore, this has to be handled as new_reference and not new_non_null_reference, otherwise a segfault will occur. --- include/boost/python/long.hpp | 4 ++-- src/long.cpp | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/boost/python/long.hpp b/include/boost/python/long.hpp index 129c61f9e4..c15604c91c 100644 --- a/include/boost/python/long.hpp +++ b/include/boost/python/long.hpp @@ -24,8 +24,8 @@ namespace detail BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(long_base, object) private: - static detail::new_non_null_reference call(object const&); - static detail::new_non_null_reference call(object const&, object const&); + static detail::new_reference call(object const&); + static detail::new_reference call(object const&, object const&); }; } diff --git a/src/long.cpp b/src/long.cpp index 1ec8ebc011..6aa2965e83 100644 --- a/src/long.cpp +++ b/src/long.cpp @@ -6,16 +6,16 @@ namespace boost { namespace python { namespace detail { -new_non_null_reference long_base::call(object const& arg_) +new_reference long_base::call(object const& arg_) { - return (detail::new_non_null_reference)PyObject_CallFunction( + return (detail::new_reference)PyObject_CallFunction( (PyObject*)&PyLong_Type, const_cast("(O)"), arg_.ptr()); } -new_non_null_reference long_base::call(object const& arg_, object const& base) +new_reference long_base::call(object const& arg_, object const& base) { - return (detail::new_non_null_reference)PyObject_CallFunction( + return (detail::new_reference)PyObject_CallFunction( (PyObject*)&PyLong_Type, const_cast("(OO)"), arg_.ptr(), base.ptr()); } From 60405cc48cf8cc2f7b32d85942b47cc39aa27b4f Mon Sep 17 00:00:00 2001 From: David Seifert Date: Wed, 25 Dec 2019 12:37:35 +0100 Subject: [PATCH 028/120] Remove Boost.Python-specific python-tag code --- Jamfile | 68 --------------------------------------------------- build/Jamfile | 4 +-- 2 files changed, 2 insertions(+), 70 deletions(-) delete mode 100644 Jamfile diff --git a/Jamfile b/Jamfile deleted file mode 100644 index 32e87d80f1..0000000000 --- a/Jamfile +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (c) 2018 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) - -import option ; -import regex ; -import python ; - -# -# The `version-suffix` rule really belongs into python.jam, and -# should be moved there. `split-version` is only duplicated here -# as a prerequisite. (See https://github.com/boostorg/build/pull/290) -# - - -# Validate the version string and extract the major/minor part we care about. -# -local rule split-version ( version ) -{ - local major-minor = [ MATCH "^([0-9]+)\.([0-9]+)(.*)$" : $(version) : 1 2 3 ] ; - if ! $(major-minor[2]) || $(major-minor[3]) - { - ECHO "Warning: \"using python\" expects a two part (major, minor) version number; got" $(version) instead ; - - # Add a zero to account for the missing digit if necessary. - major-minor += 0 ; - } - - return $(major-minor[1]) $(major-minor[2]) ; -} - -# Define a version suffix for libraries depending on Python. -# For example, Boost.Python built for Python 2.7 uses the suffix "27" -rule version-suffix ( version ) -{ - local major-minor = [ split-version $(version) ] ; - local suffix = $(major-minor:J="") ; - return $(suffix) ; -} - - -# Python build id (for Python libraries only). -python-id = [ option.get "python-buildid" ] ; -if $(python-id) -{ - PYTHON_ID = [ regex.replace $(python-id) "[*\\/:.\"\']" _ ] ; -} - -rule python-tag ( name : type ? : property-set ) -{ - local result = $(name) ; - if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB - { - local version = [ $(property-set).get ] ; - local lib-suffix = [ version-suffix $(version) ] ; - result = $(result)$(lib-suffix) ; - } - if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB && $(PYTHON_ID) - { - result = $(result)-$(PYTHON_ID) ; - } - - # forward to the boost tagging rule - return [ tag $(result) : $(type) : $(property-set) ] ; -} diff --git a/build/Jamfile b/build/Jamfile index d03d4dd084..dbc9fb2036 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -93,7 +93,7 @@ lib boost_python config-warning on:BOOST_DEBUG_PYTHON -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @$(__name__).python-tag + @python-tag @python.require-py : # default build @@ -121,7 +121,7 @@ lib boost_numpy boost_python on:BOOST_DEBUG_PYTHON -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @$(__name__).python-tag + @python-tag @python.require-py : # default build From b4fbf1840bb581a12617296b6ec2b0462906a23a Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 15 Oct 2020 11:25:18 -0400 Subject: [PATCH 029/120] Fix appveyor builds. --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index c8205eaeb1..ffcd7e3b59 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -30,7 +30,7 @@ environment: PYTHON: C:\\Python36-x64 PYTHON_VERSION: 3.6.x PYTHON_ARCH: 64 - MSVC: 16.6.5 + MSVC: 16.7.4 ARCH: x86_64 BOOST_PREFIX: C:\Libraries\boost_1_73_0 From 944fa075b321cf53a972dfd0e9bab11cc194ee15 Mon Sep 17 00:00:00 2001 From: Pat Riehecky Date: Wed, 14 Oct 2020 13:54:24 -0500 Subject: [PATCH 030/120] Stop using deprecated API calls (python-3.9) #319 --- include/boost/python/call.hpp | 4 ++-- include/boost/python/call_method.hpp | 2 +- include/boost/python/override.hpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/python/call.hpp b/include/boost/python/call.hpp index 5d2d7d2341..c057ee9a12 100644 --- a/include/boost/python/call.hpp +++ b/include/boost/python/call.hpp @@ -60,7 +60,7 @@ call(PyObject* callable ) { PyObject* const result = - PyEval_CallFunction( + PyObject_CallFunction( callable , const_cast("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil) @@ -69,7 +69,7 @@ call(PyObject* callable // This conversion *must not* be done in the same expression as // the call, because, in the special case where the result is a // reference a Python object which was created by converting a C++ - // argument for passing to PyEval_CallFunction, its reference + // argument for passing to PyObject_CallFunction, its reference // count will be 2 until the end of the full expression containing // the conversion, and that interferes with dangling // pointer/reference detection. diff --git a/include/boost/python/call_method.hpp b/include/boost/python/call_method.hpp index 410f66820e..424077eab4 100644 --- a/include/boost/python/call_method.hpp +++ b/include/boost/python/call_method.hpp @@ -69,7 +69,7 @@ call_method(PyObject* self, char const* name // This conversion *must not* be done in the same expression as // the call, because, in the special case where the result is a // reference a Python object which was created by converting a C++ - // argument for passing to PyEval_CallFunction, its reference + // argument for passing to PyObject_CallFunction, its reference // count will be 2 until the end of the full expression containing // the conversion, and that interferes with dangling // pointer/reference detection. diff --git a/include/boost/python/override.hpp b/include/boost/python/override.hpp index 39714257f9..b631226fd6 100644 --- a/include/boost/python/override.hpp +++ b/include/boost/python/override.hpp @@ -97,7 +97,7 @@ class override : public object operator()() const { detail::method_result x( - PyEval_CallFunction( + PyObject_CallFunction( this->ptr() , const_cast("()") )); @@ -132,7 +132,7 @@ detail::method_result operator()( BOOST_PP_ENUM_BINARY_PARAMS_Z(1, N, A, const& a) ) const { detail::method_result x( - PyEval_CallFunction( + PyObject_CallFunction( this->ptr() , const_cast("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_fast_arg_to_python_get, nil) From 9ad5298d0be817ebce482b6b0e4b79f3cf6a1b73 Mon Sep 17 00:00:00 2001 From: Pat Riehecky Date: Mon, 2 Mar 2020 08:29:52 -0600 Subject: [PATCH 031/120] Use python macros to stay on public API for new pythons --- src/wrapper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wrapper.cpp b/src/wrapper.cpp index f8feaef947..8b1b884769 100644 --- a/src/wrapper.cpp +++ b/src/wrapper.cpp @@ -25,7 +25,7 @@ namespace detail if ( PyMethod_Check(m.get()) - && ((PyMethodObject*)m.get())->im_self == this->m_self + && PyMethod_GET_SELF(m.get()) == this->m_self && class_object->tp_dict != 0 ) { @@ -34,7 +34,7 @@ namespace detail } - if (borrowed_f != ((PyMethodObject*)m.get())->im_func) + if (borrowed_f != PyMethod_GET_FUNCTION(m.get())) return override(m); } } From d9f06052e28873037db7f98629bce72182a42410 Mon Sep 17 00:00:00 2001 From: Pat Riehecky Date: Mon, 29 Jun 2020 10:51:58 -0500 Subject: [PATCH 032/120] Convert Python 3.1+ to use public C API for filenames --- src/exec.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/exec.cpp b/src/exec.cpp index 171c6f4189..b2eabe59f6 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -104,14 +104,22 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l if (local.is_none()) local = global; // should be 'char const *' but older python versions don't use 'const' yet. char *f = const_cast(filename); - // Let python open the file to avoid potential binary incompatibilities. -#if PY_VERSION_HEX >= 0x03040000 - FILE *fs = _Py_fopen(f, "r"); +#if PY_VERSION_HEX >= 0x03010000 + // Let python manage any UTF bits to avoid potential incompatibilities. + PyObject *fo = Py_BuildValue("s", f); + PyObject *fb = Py_None; + PyUnicode_FSConverter(fo, &fb); + f = PyBytes_AsString(fb); + FILE *fs = fopen(f, "r"); + Py_DECREF(fo); + Py_DECREF(fb); #elif PY_VERSION_HEX >= 0x03000000 + // Let python open the file to avoid potential binary incompatibilities. PyObject *fo = Py_BuildValue("s", f); - FILE *fs = _Py_fopen(fo, "r"); + FILE *fs = _Py_fopen(fo, "r"); // Private CPython API Py_DECREF(fo); #else + // Let python open the file to avoid potential binary incompatibilities. PyObject *pyfile = PyFile_FromString(f, const_cast("r")); if (!pyfile) throw std::invalid_argument(std::string(f) + " : no such file"); python::handle<> file(pyfile); From f1320bf30b4887aff28b9fc67b98f6f8be8c3684 Mon Sep 17 00:00:00 2001 From: Pat Riehecky Date: Tue, 13 Oct 2020 13:34:52 -0500 Subject: [PATCH 033/120] Add pypy3 to TravisCI matrix --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index ef7828c60a..657386bb0f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,20 +28,26 @@ jobs: env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 - os: linux env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 + - os: linux + env: CXX=g++ PYTHON=pypy3 CXXFLAGS=-std=c++11 - os: osx env: CXX=clang++ PYTHON=python CXXFLAGS=-std=c++11 - env: PYTHON=python DOC=1 allow_failures: + - os: linux + env: CXX=g++ PYTHON=pypy3 CXXFLAGS=-std=c++11 - os: osx addons: apt: sources: - ubuntu-toolchain-r-test + - pypy packages: - gcc - g++ - clang + - pypy3-dev - python3-pip - python-numpy - python-sphinx From 8328a4f53539483c630a0fcb115f8b7f224308b0 Mon Sep 17 00:00:00 2001 From: Thomas Kent Date: Sun, 13 Dec 2020 08:00:54 -0600 Subject: [PATCH 034/120] New VS2019 version on appveyor --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index ffcd7e3b59..7f4fd2bc6f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -30,7 +30,7 @@ environment: PYTHON: C:\\Python36-x64 PYTHON_VERSION: 3.6.x PYTHON_ARCH: 64 - MSVC: 16.7.4 + MSVC: 16.8.1 ARCH: x86_64 BOOST_PREFIX: C:\Libraries\boost_1_73_0 From c9521a8ef547ee220cb2a55b285c8f361853a058 Mon Sep 17 00:00:00 2001 From: Thomas Kent Date: Fri, 18 Dec 2020 05:52:03 -0600 Subject: [PATCH 035/120] Updated VS2019 to 16.8.3 --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 7f4fd2bc6f..8c229c2b0a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -30,7 +30,7 @@ environment: PYTHON: C:\\Python36-x64 PYTHON_VERSION: 3.6.x PYTHON_ARCH: 64 - MSVC: 16.8.1 + MSVC: 16.8.3 ARCH: x86_64 BOOST_PREFIX: C:\Libraries\boost_1_73_0 From 97a8550a9fbd742fdf4be3def21c695626333c85 Mon Sep 17 00:00:00 2001 From: Tom Kent Date: Tue, 22 Dec 2020 15:56:09 -0600 Subject: [PATCH 036/120] Using docker images to execut the github actions for testing (#335) Introduce github action-based test workflow for Ubuntu. --- .github/workflows/build_test_docker.yml | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/build_test_docker.yml diff --git a/.github/workflows/build_test_docker.yml b/.github/workflows/build_test_docker.yml new file mode 100644 index 0000000000..23550cfa9a --- /dev/null +++ b/.github/workflows/build_test_docker.yml @@ -0,0 +1,47 @@ +name: Build and Test - Linux Docker + +on: [ push, pull_request ] + +jobs: + build: + + # ubuntu-latest will be shortly upgrading to this + runs-on: ubuntu-20.04 + + strategy: + fail-fast: false + matrix: + python: [ python, python3 ] + cxx: [ g++, clang++ ] + std: [ c++98, c++11] + include: + # Add the appropriate docker image for each compiler. + # The images from teeks99/boost-python-test already have boost::python + # pre-reqs installed, see: + # https://github.com/teeks99/boost-python-test-docker + - cxx: clang++ + docker-img: teeks99/boost-python-test:clang-11_1.66.0 + - cxx: g++ + docker-img: teeks99/boost-python-test:gcc-9_1.66.0 + + container: + image: ${{ matrix.docker-img }} + + steps: + - uses: actions/checkout@v2 + + - name: Test + run: | + ${{ matrix.python }} --version + ${{ matrix.cxx }} --version + faber -v + ls -l ${BOOST_PY_DEPS} + + sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber + + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build test.report \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + -j`nproc` From 3dd6bcf39f4bb6dd51dc87255e6c055253fb122d Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Wed, 23 Dec 2020 19:22:22 -0500 Subject: [PATCH 037/120] Add OSX tests. --- .github/workflows/test-osx.yml | 45 +++++++++++++++++++ ...{build_test_docker.yml => test-ubuntu.yml} | 30 +++++++------ 2 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 .github/workflows/test-osx.yml rename .github/workflows/{build_test_docker.yml => test-ubuntu.yml} (66%) diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml new file mode 100644 index 0000000000..19928d875b --- /dev/null +++ b/.github/workflows/test-osx.yml @@ -0,0 +1,45 @@ +name: Test OSX + +on: [push, pull_request] + +jobs: + build: + runs-on: macOS-latest + + strategy: + fail-fast: false + matrix: + python-version: [3.6] + cxx: [clang++] + std: [c++98, c++11, c++14] # TODO: c++17 is failing ! + + steps: + - uses: actions/checkout@v2 + - name: setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: setup prerequisites + run: | + brew install boost + python -m pip install --upgrade pip + python -m pip install setuptools faber + - name: build + run: | + python --version + ${{ matrix.cxx }} --version + faber -v + sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber + faber \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + -j`sysctl -n hw.ncpu` + - name: test + run: | + faber \ + --builddir=build\ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + -j`sysctl -n hw.ncpu` \ + test.report diff --git a/.github/workflows/build_test_docker.yml b/.github/workflows/test-ubuntu.yml similarity index 66% rename from .github/workflows/build_test_docker.yml rename to .github/workflows/test-ubuntu.yml index 23550cfa9a..61a295981f 100644 --- a/.github/workflows/build_test_docker.yml +++ b/.github/workflows/test-ubuntu.yml @@ -1,19 +1,17 @@ -name: Build and Test - Linux Docker +name: Test Ubuntu -on: [ push, pull_request ] +on: [push, pull_request] jobs: build: - - # ubuntu-latest will be shortly upgrading to this - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python: [ python, python3 ] - cxx: [ g++, clang++ ] - std: [ c++98, c++11] + python: [python, python3] + cxx: [g++, clang++] + std: [c++98, c++11, c++14, c++17] include: # Add the appropriate docker image for each compiler. # The images from teeks99/boost-python-test already have boost::python @@ -30,18 +28,24 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Test + - name: build run: | ${{ matrix.python }} --version ${{ matrix.cxx }} --version faber -v - ls -l ${BOOST_PY_DEPS} - sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber - faber \ --with-boost-include=${BOOST_PY_DEPS} \ - --builddir=build test.report \ + --builddir=build \ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ -j`nproc` + - name: test + run: | + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + -j`nproc` \ + test.report From 108c93f7c3b5437ea8551c01b0205076e2bf6de0 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Wed, 23 Dec 2020 23:36:14 -0500 Subject: [PATCH 038/120] Deploy documentation via github actions. --- .ci/faber | 4 +++ .github/workflows/deploy-documentation.yml | 37 ++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 .github/workflows/deploy-documentation.yml diff --git a/.ci/faber b/.ci/faber index b23e8a18ba..ddb36ddf66 100644 --- a/.ci/faber +++ b/.ci/faber @@ -1,3 +1,7 @@ +# -*- python -*- + +from faber.tools.boost import boostbook from faber.tools.python import python +bb = boostbook(prefix='/usr/share/boostbook') p = python(command='$PYTHON') diff --git a/.github/workflows/deploy-documentation.yml b/.github/workflows/deploy-documentation.yml new file mode 100644 index 0000000000..83a0f08945 --- /dev/null +++ b/.github/workflows/deploy-documentation.yml @@ -0,0 +1,37 @@ +name: deploy documentation + +on: [push, pull_request] + +jobs: + deploy: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: setup + run: | + sudo apt-get update + sudo apt-get install \ + libboost1.71-tools-dev \ + python3 \ + python3-numpy \ + python3-sphinx \ + xsltproc \ + docbook-xsl + sudo python3 -m pip install --upgrade pip + sudo python3 -m pip install faber + - name: build + run: | + sed -e "s/\$PYTHON/python3/g" .ci/faber > ~/.faber + faber --builddir=build doc.html + if [ "${GITHUB_REF##*/}" == master ]; then + echo "destination_dir=doc/html" >> $GITHUB_ENV + else + echo "destination_dir=doc/develop/html" >> $GITHUB_ENV + fi + - name: deploy + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: build/doc/html + destination_dir: ${{ env.destination_dir }} + keep_files: true From 5e4f6278e01f018c32cebc4ffc3b75a743fb1042 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 26 Dec 2020 13:56:45 -0500 Subject: [PATCH 039/120] Remove travis-ci logic. --- .ci/upload_docs.sh | 58 ---------------------- .travis.yml | 117 --------------------------------------------- README.md | 2 +- 3 files changed, 1 insertion(+), 176 deletions(-) delete mode 100755 .ci/upload_docs.sh delete mode 100644 .travis.yml diff --git a/.ci/upload_docs.sh b/.ci/upload_docs.sh deleted file mode 100755 index 1e6f6b5ced..0000000000 --- a/.ci/upload_docs.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -set -e # Exit with nonzero exit code if anything fails - -SOURCE_BRANCH="master" -TARGET_BRANCH="gh-pages" - -# Pull requests and commits to other branches shouldn't try to deploy, just build to verify -if [ "$TRAVIS_PULL_REQUEST" != "false" ] || \ - [ "$TRAVIS_BRANCH" != master -a \ - "$TRAVIS_BRANCH" != develop -a \ - "$TRAVIS_BRANCH" != travis ]; then - echo "No docs to upload." - exit 0 -fi - -if [ -z "$GH_TOKEN" ]; then - echo "Error: GH_TOKEN is undefined" - exit 1 -fi - -# Save some useful information -REPO=`git config remote.origin.url` -SHA=`git rev-parse --verify HEAD` - -# build happens to contain the "doc/html" tree that we want to push -# into the gh-pages branch. So we step into that directory, create a new repo, -# set the remote appropriately, then commit and push. -cd build -git init -git config user.name "Travis CI" -git config user.email "travis-ci" - -# Make sure 'GH_TOKEN' is set (as 'secure' variable) in .travis.yml -git remote add upstream "https://$GH_TOKEN@github.com/boostorg/python.git" -git fetch upstream -git reset upstream/gh-pages - -# Prepare version. -if [ "$TRAVIS_BRANCH" = develop -o "$TRAVIS_BRANCH" = travis ]; then - mkdir -p develop/doc/ - cp ../index.html develop/ - cp ../doc/index.html develop/doc/ - cp -a doc/html develop/doc/ - git add develop/index.html - git add develop/doc/index.html - git add -A develop/doc/html -else - cp ../index.html . - cp ../doc/index.html doc/ - git add index.html - git add doc/index.html - git add -A doc/html -fi -# Commit the new version. -git commit -m "Deploy to GitHub Pages: ${SHA}" - -# Now that we're all set up, we can push. -git push -q upstream HEAD:gh-pages diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 657386bb0f..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,117 +0,0 @@ -# -# 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) - -dist: bionic - -language: cpp - -env: - global: - - secure: BRNUkxN3p8f+uYKWC3Hr0VPqZA0PxbWr1DJlcI4hbiZtzKhMCWjDmd9UW9CzzexqeOxpd+9s0G87qvOur+wMSVxugDxtTesZrh1czXHeSVxgQrYD783XJtQJ9aYypbChkiboRD6Xpmbq7itwMuHBJMFtCuDxMynpU1jWwkyTf2Y= - -jobs: - include: - - os: linux - env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++98 - - os: linux - env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++11 - - os: linux - env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++98 - - os: linux - env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11 - - os: linux - env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 - - os: linux - env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 - - os: linux - env: CXX=g++ PYTHON=pypy3 CXXFLAGS=-std=c++11 - - os: osx - env: CXX=clang++ PYTHON=python CXXFLAGS=-std=c++11 - - env: PYTHON=python DOC=1 - allow_failures: - - os: linux - env: CXX=g++ PYTHON=pypy3 CXXFLAGS=-std=c++11 - - os: osx - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - pypy - packages: - - gcc - - g++ - - clang - - pypy3-dev - - python3-pip - - python-numpy - - python-sphinx - - python3-dev - - python3-numpy - - libboost-all-dev - - xsltproc - - docbook-xsl - - python-docutils - - -cache: - directories: - - $HOME/Boost - -install: - # Install our own version of Boost (the subset we need) as the system version is - # too old (for C++11 support). - - | - if [ ! -d $HOME/Boost/tools/boostbook ]; then - echo "rebuilding Boost prerequisites." - wget https://sourceforge.net/projects/boost/files/boost/1.66.0/boost_1_66_0.tar.gz/download - tar xf download - pushd boost_1_66_0 - ./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 - else - echo "using cached Boost prerequisites." - fi - # Install Faber, the build tool. - python3 -m pip install setuptools - python3 -m pip install faber - #date=2020-08-01 - #wget https://github.com/stefanseefeld/faber/archive/snapshot/$date.tar.gz - #tar xf $date.tar.gz - #pushd faber-snapshot-$date - #sudo python3 setup.py install - #popd - -before_script: -- sed -e "s/\$PYTHON/$PYTHON/g" .ci/faber > ~/.faber -- $PYTHON --version -- faber -h -- ls -l $HOME/Boost - -script: -- | - if [ "$DOC" ]; then - BOOST_ROOT=$HOME/Boost faber --builddir=build doc.html - else - faber --with-boost-include=$HOME/Boost --builddir=build test.report cxx.name=$CXX cxxflags=$CXXFLAGS -j8 - fi - -after_success: -# Upload docs only when building upstream. -- | - if [ "$DOC" -a \ - "$TRAVIS_REPO_SLUG" = "boostorg/python" -a \ - "$TRAVIS_PULL_REQUEST" = "false" ]; then - export GH_TOKEN - .ci/upload_docs.sh - fi diff --git a/README.md b/README.md index 7646d3a877..61f9b24ef0 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ See the [Boost.Python](http://boostorg.github.io/python) documentation for detai **Hint :** Check out the [development version](http://boostorg.github.io/python/develop) of the documentation to see work in progress. -# Building [![Build Status](https://travis-ci.org/boostorg/python.svg?branch=develop)](https://travis-ci.org/boostorg/python) [![Build status](https://ci.appveyor.com/api/projects/status/cgx9xma6v3gjav92/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/python/branch/develop) +# Building ![Test Ubuntu](https://github.com/boostorg/python/workflows/Test%20Ubuntu/badge.svg) ![Test OSX](https://github.com/boostorg/python/workflows/Test%20OSX/badge.svg) [![Build status](https://ci.appveyor.com/api/projects/status/cgx9xma6v3gjav92/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/python/branch/develop) While Boost.Python is part of the Boost C++ Libraries super-project, and thus can be compiled as part of Boost, it can also be compiled and installed stand-alone, i.e. against a pre-installed Boost package. From cd953cff06bfaca086648795e1cbed260b00a156 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Fri, 25 Dec 2020 15:42:48 -0500 Subject: [PATCH 040/120] Replace appveyor by github actions. --- .appveyor.yml | 111 -------------- .ci/install.ps1 | 229 ----------------------------- .ci/run_with_env.cmd | 88 ----------- .github/workflows/test-windows.yml | 39 +++++ README.md | 3 +- 5 files changed, 40 insertions(+), 430 deletions(-) delete mode 100644 .appveyor.yml delete mode 100644 .ci/install.ps1 delete mode 100644 .ci/run_with_env.cmd create mode 100644 .github/workflows/test-windows.yml diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 8c229c2b0a..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,111 +0,0 @@ -environment: - global: - # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the - # /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" - - matrix: - - # Pre-installed Python versions, which Appveyor may upgrade to - # a later point release. - # See: http://www.appveyor.com/docs/installed-software#python - - - PYTHON: C:\\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - MSVC: 12.0 - ARCH: x86_64 - BOOST_PREFIX: C:\Libraries\boost_1_66_0 - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - PYTHON: C:\\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - MSVC: 15.9.19 - ARCH: x86_64 - BOOST_PREFIX: C:\Libraries\boost_1_69_0 - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - PYTHON: C:\\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - MSVC: 16.8.3 - ARCH: x86_64 - BOOST_PREFIX: C:\Libraries\boost_1_73_0 - -install: - # If there is a newer build queued for the same PR, cancel this one. - # The AppVeyor 'rollout builds' option is supposed to serve the same - # purpose but it is problematic because it tends to cancel builds pushed - # directly to master instead of just PR builds (or the converse). - # credits: JuliaLang developers. - - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` - https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` - Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` - throw "There are newer queued builds for this pull request, failing early." } - - ECHO "Filesystem root:" - - ps: "ls \"C:/\"" - - ECHO "Installed libraries:" - - ps: "ls \"C:/Libraries/\"" - ## This path doesn't exist with the VS 2017 worker images - #- ECHO "Installed SDKs:" - #- ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" - - # Install Python (from the official .msi of http://python.org) and pip when - # not already installed. - - ps: if (-not(Test-Path($env:PYTHON))) { & .ci\install.ps1 } - - # Prepend newly installed Python to the PATH of this build (this cannot be - # done from inside the powershell script as it would require to restart - # the parent CMD process). - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - # Check that we have the expected version and architecture for Python - - "python --version" - - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - - # Upgrade to the latest version of pip to avoid it displaying warnings - # about it being out of date. - - "python -m pip install --disable-pip-version-check --user --upgrade pip" - - # Install the build dependencies of the project. If some dependencies contain - # 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 - - - curl -LfsS -o vswhere.exe https://github.com/Microsoft/vswhere/releases/download/2.8.4/vswhere.exe - #- | - # curl -LfsS -o faber.tar.gz https://github.com/stefanseefeld/faber/archive/snapshot/2020-08-01.tar.gz - # tar xf faber.tar.gz - # CD faber-snapshot-2020-08-01 - # python setup.py install - # CD .. - - python -m pip install faber - # report the available MSVC compilers - - faber --log=tools --info=tools cxx - - easy_install sphinx - - python -m pip install numpy - - set FARGS=--log=summary --log=output --log=actions --log=commands --with-boost-include=%BOOST_PREFIX% target.arch=%ARCH% cxx.name=msvc cxx.version=%MSVC% - -build_script: - - faber %FARGS% config || type config.log - - faber %FARGS% -j8 - -test_script: - - faber %FARGS% -j8 test.report - -after_test: - # If tests are successful, create binary packages for the project. - #- "%CMD_IN_ENV% python setup.py bdist_wheel" - #- "%CMD_IN_ENV% python setup.py bdist_wininst" - #- "%CMD_IN_ENV% python setup.py bdist_msi" - #- ps: "ls dist" - -#artifacts: - # Archive the generated packages in the ci.appveyor.com build report. - #- path: dist\* - -#on_success: -# - TODO: upload the content of dist/*.whl to a public wheelhouse -# diff --git a/.ci/install.ps1 b/.ci/install.ps1 deleted file mode 100644 index 94d6f01813..0000000000 --- a/.ci/install.ps1 +++ /dev/null @@ -1,229 +0,0 @@ -# Sample script to install Python and pip under Windows -# Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer -# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ - -$MINICONDA_URL = "http://repo.continuum.io/miniconda/" -$BASE_URL = "https://www.python.org/ftp/python/" -$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" -$GET_PIP_PATH = "C:\get-pip.py" - -$PYTHON_PRERELEASE_REGEX = @" -(?x) -(?\d+) -\. -(?\d+) -\. -(?\d+) -(?[a-z]{1,2}\d+) -"@ - - -function Download ($filename, $url) { - $webclient = New-Object System.Net.WebClient - - $basedir = $pwd.Path + "\" - $filepath = $basedir + $filename - if (Test-Path $filename) { - Write-Host "Reusing" $filepath - return $filepath - } - - # Download and retry up to 3 times in case of network transient errors. - Write-Host "Downloading" $filename "from" $url - $retry_attempts = 2 - for ($i = 0; $i -lt $retry_attempts; $i++) { - try { - $webclient.DownloadFile($url, $filepath) - break - } - Catch [Exception]{ - Start-Sleep 1 - } - } - if (Test-Path $filepath) { - Write-Host "File saved at" $filepath - } else { - # Retry once to get the error message if any at the last try - $webclient.DownloadFile($url, $filepath) - } - return $filepath -} - - -function ParsePythonVersion ($python_version) { - if ($python_version -match $PYTHON_PRERELEASE_REGEX) { - return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro, - $matches.prerelease) - } - $version_obj = [version]$python_version - return ($version_obj.major, $version_obj.minor, $version_obj.build, "") -} - - -function DownloadPython ($python_version, $platform_suffix) { - $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version - - if (($major -le 2 -and $micro -eq 0) ` - -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) ` - ) { - $dir = "$major.$minor" - $python_version = "$major.$minor$prerelease" - } else { - $dir = "$major.$minor.$micro" - } - - if ($prerelease) { - if (($major -le 2) ` - -or ($major -eq 3 -and $minor -eq 1) ` - -or ($major -eq 3 -and $minor -eq 2) ` - -or ($major -eq 3 -and $minor -eq 3) ` - ) { - $dir = "$dir/prev" - } - } - - if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) { - $ext = "msi" - if ($platform_suffix) { - $platform_suffix = ".$platform_suffix" - } - } else { - $ext = "exe" - if ($platform_suffix) { - $platform_suffix = "-$platform_suffix" - } - } - - $filename = "python-$python_version$platform_suffix.$ext" - $url = "$BASE_URL$dir/$filename" - $filepath = Download $filename $url - return $filepath -} - - -function InstallPython ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -eq "32") { - $platform_suffix = "" - } else { - $platform_suffix = "amd64" - } - $installer_path = DownloadPython $python_version $platform_suffix - $installer_ext = [System.IO.Path]::GetExtension($installer_path) - Write-Host "Installing $installer_path to $python_home" - $install_log = $python_home + ".log" - if ($installer_ext -eq '.msi') { - InstallPythonMSI $installer_path $python_home $install_log - } else { - InstallPythonEXE $installer_path $python_home $install_log - } - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallPythonEXE ($exepath, $python_home, $install_log) { - $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home" - RunCommand $exepath $install_args -} - - -function InstallPythonMSI ($msipath, $python_home, $install_log) { - $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home" - $uninstall_args = "/qn /x $msipath" - RunCommand "msiexec.exe" $install_args - if (-not(Test-Path $python_home)) { - Write-Host "Python seems to be installed else-where, reinstalling." - RunCommand "msiexec.exe" $uninstall_args - RunCommand "msiexec.exe" $install_args - } -} - -function RunCommand ($command, $command_args) { - Write-Host $command $command_args - Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru -} - - -function InstallPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $python_path = $python_home + "\python.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $webclient = New-Object System.Net.WebClient - $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) - Write-Host "Executing:" $python_path $GET_PIP_PATH - & $python_path $GET_PIP_PATH - } else { - Write-Host "pip already installed." - } -} - - -function DownloadMiniconda ($python_version, $platform_suffix) { - if ($python_version -eq "3.4") { - $filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe" - } else { - $filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe" - } - $url = $MINICONDA_URL + $filename - $filepath = Download $filename $url - return $filepath -} - - -function InstallMiniconda ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -eq "32") { - $platform_suffix = "x86" - } else { - $platform_suffix = "x86_64" - } - $filepath = DownloadMiniconda $python_version $platform_suffix - Write-Host "Installing" $filepath "to" $python_home - $install_log = $python_home + ".log" - $args = "/S /D=$python_home" - Write-Host $filepath $args - Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallMinicondaPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $conda_path = $python_home + "\Scripts\conda.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $args = "install --yes pip" - Write-Host $conda_path $args - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru - } else { - Write-Host "pip already installed." - } -} - -function main () { - InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON - InstallPip $env:PYTHON -} - -main \ No newline at end of file diff --git a/.ci/run_with_env.cmd b/.ci/run_with_env.cmd deleted file mode 100644 index 5da547c499..0000000000 --- a/.ci/run_with_env.cmd +++ /dev/null @@ -1,88 +0,0 @@ -:: To build extensions for 64 bit Python 3, we need to configure environment -:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) -:: -:: To build extensions for 64 bit Python 2, we need to configure environment -:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) -:: -:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific -:: environment configurations. -:: -:: Note: this script needs to be run with the /E:ON and /V:ON flags for the -:: cmd interpreter, at least for (SDK v7.0) -:: -:: More details at: -:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows -:: http://stackoverflow.com/a/13751649/163740 -:: -:: Author: Olivier Grisel -:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ -:: -:: Notes about batch files for Python people: -:: -:: Quotes in values are literally part of the values: -:: SET FOO="bar" -:: FOO is now five characters long: " b a r " -:: If you don't want quotes, don't include them on the right-hand side. -:: -:: The CALL lines at the end of this file look redundant, but if you move them -:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y -:: case, I don't know why. -@ECHO OFF - -SET COMMAND_TO_RUN=%* -SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows -SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf - -:: Extract the major and minor versions, and allow for the minor version to be -:: more than 9. This requires the version number to have two dots in it. -SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1% -IF "%PYTHON_VERSION:~3,1%" == "." ( - SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1% -) ELSE ( - SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2% -) - -:: Based on the Python version, determine what SDK version to use, and whether -:: to set the SDK for 64-bit. -IF %MAJOR_PYTHON_VERSION% == 2 ( - SET WINDOWS_SDK_VERSION="v7.0" - SET SET_SDK_64=Y -) ELSE ( - IF %MAJOR_PYTHON_VERSION% == 3 ( - SET WINDOWS_SDK_VERSION="v7.1" - IF %MINOR_PYTHON_VERSION% LEQ 4 ( - SET SET_SDK_64=Y - ) ELSE ( - SET SET_SDK_64=N - IF EXIST "%WIN_WDK%" ( - :: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/ - REN "%WIN_WDK%" 0wdf - ) - ) - ) ELSE ( - ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" - EXIT 1 - ) -) - -IF %PYTHON_ARCH% == 64 ( - IF %SET_SDK_64% == Y ( - ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture - SET DISTUTILS_USE_SDK=1 - SET MSSdk=1 - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 - ) ELSE ( - ECHO Using default MSVC build environment for 64 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 - ) -) ELSE ( - ECHO Using default MSVC build environment for 32 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 -) diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml new file mode 100644 index 0000000000..4d5878ea7a --- /dev/null +++ b/.github/workflows/test-windows.yml @@ -0,0 +1,39 @@ +name: Test Windows + +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + python-version: [3.7] + + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: setup boost prerequisites + uses: lukka/run-vcpkg@v6 + with: + vcpkgGitCommitId: '8a9a97315aefb3f8bc5d81bf66ca0025938b9c91' + vcpkgDirectory: '${{ runner.workspace }}/vcpkg' + vcpkgTriplet: x64-windows + vcpkgArguments: boost-config boost-core boost-function boost-graph boost-iterator boost-lexical-cast boost-mpl boost-preprocessor boost-smart-ptr boost-static-assert + + - name: setup faber + #shell: 'bash' + run: | + python -m pip install --upgrade pip + python -m pip install setuptools faber numpy + faber --info=tools cxx + - name: build + shell: cmd + run: | + faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}/vcpkg/installed/x64-windows/include -j4 + - name: test + shell: cmd + run: | + faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}/vcpkg/installed/x64-windows/include -j4 test.report diff --git a/README.md b/README.md index 61f9b24ef0..f57b97505a 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,7 @@ See the [Boost.Python](http://boostorg.github.io/python) documentation for detai **Hint :** Check out the [development version](http://boostorg.github.io/python/develop) of the documentation to see work in progress. -# Building ![Test Ubuntu](https://github.com/boostorg/python/workflows/Test%20Ubuntu/badge.svg) ![Test OSX](https://github.com/boostorg/python/workflows/Test%20OSX/badge.svg) [![Build status](https://ci.appveyor.com/api/projects/status/cgx9xma6v3gjav92/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/python/branch/develop) - +# Building ![Test Ubuntu](https://github.com/boostorg/python/workflows/Test%20Ubuntu/badge.svg) ![Test OSX](https://github.com/boostorg/python/workflows/Test%20OSX/badge.svg) ![Test Windows](https://github.com/boostorg/python/workflows/Test%20Windows/badge.svg) While Boost.Python is part of the Boost C++ Libraries super-project, and thus can be compiled as part of Boost, it can also be compiled and installed stand-alone, i.e. against a pre-installed Boost package. From 500194edb7833d0627ce7a2595fec49d0aae2484 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Fri, 13 Nov 2020 21:17:24 -0500 Subject: [PATCH 041/120] Fix Python 3.10 (PEP-620) incompatibility. --- include/boost/python/detail/wrap_python.hpp | 4 ++++ include/boost/python/object/make_instance.hpp | 2 +- src/object/class.cpp | 15 +++++---------- src/object/enum.cpp | 2 +- src/object/function.cpp | 2 +- src/object/life_support.cpp | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 9d5f5422a2..037e4bf2ec 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -227,7 +227,11 @@ typedef int pid_t; # define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, +#endif +#if PY_VERSION_HEX < 0x030900A4 +# define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0) +# define Py_SET_SIZE(obj, size) ((Py_SIZE(obj) = (size)), (void)0) #endif diff --git a/include/boost/python/object/make_instance.hpp b/include/boost/python/object/make_instance.hpp index 31ec08f7c3..5eb3aa9d9c 100644 --- a/include/boost/python/object/make_instance.hpp +++ b/include/boost/python/object/make_instance.hpp @@ -47,7 +47,7 @@ struct make_instance_impl // Note the position of the internally-stored Holder, // for the sake of destruction - Py_SIZE(instance) = offsetof(instance_t, storage); + Py_SET_SIZE(instance, offsetof(instance_t, storage)); // Release ownership of the python object protect.cancel(); diff --git a/src/object/class.cpp b/src/object/class.cpp index 9bb9683a31..c6bab76009 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -208,7 +208,7 @@ namespace objects { if (static_data_object.tp_dict == 0) { - Py_TYPE(&static_data_object) = &PyType_Type; + Py_SET_TYPE(&static_data_object, &PyType_Type); static_data_object.tp_base = &PyProperty_Type; if (PyType_Ready(&static_data_object)) return 0; @@ -316,7 +316,7 @@ namespace objects { if (class_metatype_object.tp_dict == 0) { - Py_TYPE(&class_metatype_object) = &PyType_Type; + Py_SET_TYPE(&class_metatype_object, &PyType_Type); class_metatype_object.tp_base = &PyType_Type; if (PyType_Ready(&class_metatype_object)) return type_handle(); @@ -374,12 +374,7 @@ namespace objects // like, so we'll store the total size of the object // there. A negative number indicates that the extra // instance memory is not yet allocated to any holders. -#if PY_VERSION_HEX >= 0x02060000 - Py_SIZE(result) = -#else - result->ob_size = -#endif - -(static_cast(offsetof(instance<>,storage) + instance_size)); + Py_SET_SIZE(result,-static_cast(offsetof(instance<>,storage) + instance_size)); } return (PyObject*)result; } @@ -470,7 +465,7 @@ namespace objects { if (class_type_object.tp_dict == 0) { - Py_TYPE(&class_type_object) = incref(class_metatype().get()); + Py_SET_TYPE(&class_type_object, incref(class_metatype().get())); class_type_object.tp_base = &PyBaseObject_Type; if (PyType_Ready(&class_type_object)) return type_handle(); @@ -739,7 +734,7 @@ void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std: assert(holder_offset >= offsetof(objects::instance<>,storage)); // Record the fact that the storage is occupied, noting where it starts - Py_SIZE(self) = holder_offset; + Py_SET_SIZE(self, holder_offset); return (char*)self + holder_offset; } else diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 10122ad1da..293e705899 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -153,7 +153,7 @@ namespace { if (enum_type_object.tp_dict == 0) { - Py_TYPE(&enum_type_object) = incref(&PyType_Type); + Py_SET_TYPE(&enum_type_object, incref(&PyType_Type)); #if PY_VERSION_HEX >= 0x03000000 enum_type_object.tp_base = &PyLong_Type; #else diff --git a/src/object/function.cpp b/src/object/function.cpp index 9d4745d102..787679e138 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -107,7 +107,7 @@ function::function( PyObject* p = this; if (Py_TYPE(&function_type) == 0) { - Py_TYPE(&function_type) = &PyType_Type; + Py_SET_TYPE(&function_type, &PyType_Type); ::PyType_Ready(&function_type); } diff --git a/src/object/life_support.cpp b/src/object/life_support.cpp index b7e9aa861e..281c3bffc5 100644 --- a/src/object/life_support.cpp +++ b/src/object/life_support.cpp @@ -93,7 +93,7 @@ PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) if (Py_TYPE(&life_support_type) == 0) { - Py_TYPE(&life_support_type) = &PyType_Type; + Py_SET_TYPE(&life_support_type, &PyType_Type); PyType_Ready(&life_support_type); } From 30dd3fe8b1c83a1120e1b3f61a17bbd3bc603de9 Mon Sep 17 00:00:00 2001 From: Cedric Schmeits Date: Tue, 20 Oct 2020 15:22:22 +0200 Subject: [PATCH 042/120] added includes for call_method.hpp and def.hpp --- doc/reference/call_method.qbk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/reference/call_method.qbk b/doc/reference/call_method.qbk index 926763cebc..e8d22f9fc8 100644 --- a/doc/reference/call_method.qbk +++ b/doc/reference/call_method.qbk @@ -20,6 +20,8 @@ C++ Module Definition `` #include #include +#include +#include #include #include From 0f1945060f608be68bf8e642503c6f9bdc4fe19c Mon Sep 17 00:00:00 2001 From: Cedric Schmeits Date: Tue, 20 Oct 2020 17:14:01 +0200 Subject: [PATCH 043/120] noncopyable is located in the boost namespace --- doc/reference/call_method.qbk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/reference/call_method.qbk b/doc/reference/call_method.qbk index e8d22f9fc8..fcf68667d0 100644 --- a/doc/reference/call_method.qbk +++ b/doc/reference/call_method.qbk @@ -30,7 +30,7 @@ class Base { public: virtual char const* class_name() const { return "Base"; } - virtual ~Base(); + virtual ~Base() {}; }; bool is_base(Base* b) @@ -58,7 +58,7 @@ BOOST_PYTHON_MODULE(my_module) { def("is_base", is_base); - class_("Base") + class_("Base") .def("class_name", &Base_callback::Base_name) ; From cbd2d9f033c61d29d0a1df14951f4ec91e7d05cd Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 6 Jan 2021 10:07:29 +0100 Subject: [PATCH 044/120] Fix compatibility with Python 3.10.0a4: fopen Replace private _Py_fopen() with public fopen(): private _Py_fopen() function was removed in 3.10.0a4: https://bugs.python.org/issue32381 --- src/exec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/exec.cpp b/src/exec.cpp index b2eabe59f6..dd0c33103f 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -116,7 +116,7 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l #elif PY_VERSION_HEX >= 0x03000000 // Let python open the file to avoid potential binary incompatibilities. PyObject *fo = Py_BuildValue("s", f); - FILE *fs = _Py_fopen(fo, "r"); // Private CPython API + FILE *fs = fopen(fo, "r"); Py_DECREF(fo); #else // Let python open the file to avoid potential binary incompatibilities. From bffcb99ae7ae99ed41ef6df0e517d2aebdc66811 Mon Sep 17 00:00:00 2001 From: Edward Diener Date: Thu, 21 Jan 2021 00:04:25 -0500 Subject: [PATCH 045/120] [skip ci] Add "cxxstd" json field. The "cxxstd" json field is being added to each Boost library's meta json information for libraries in order to specify the minumum C++ standard compilation level. The value of this field matches one of the values for 'cxxstd' in Boost.Build. The purpose of doing this is to provide information for the Boost website documentation for each library which will specify the minimum C++ standard compilation that an end-user must employ in order to use the particular library. This will aid end-users who want to know if they can successfully use a Boost library based on their C++ compiler's compilation level, without having to search the library's documentation to find this out. --- meta/libraries.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meta/libraries.json b/meta/libraries.json index e2f2a05472..80f20f846c 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -10,5 +10,6 @@ ], "maintainers": [ "Stefan Seefeld " - ] + ], + "cxxstd": "03" } From f7254f5d8ab113908e2ad3721e5122e5c5ef7b89 Mon Sep 17 00:00:00 2001 From: Dmitry Bely Date: Wed, 3 Feb 2021 13:49:32 +0300 Subject: [PATCH 046/120] Add a test case for issue #280 --- test/fabscript | 1 + test/module_init_exception.cpp | 14 ++++++++++++++ test/module_init_exception.py | 12 ++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 test/module_init_exception.cpp create mode 100644 test/module_init_exception.py diff --git a/test/fabscript b/test/fabscript index 03e4c6f919..eb9379e0ac 100644 --- a/test/fabscript +++ b/test/fabscript @@ -67,6 +67,7 @@ for t in [('injected',), ('args',), ('raw_ctor',), ('exception_translator',), + ('module_init_exception',), ('test_enum', ['enum_ext']), ('test_cltree', ['cltree']), ('newtest', ['m1', 'm2']), diff --git a/test/module_init_exception.cpp b/test/module_init_exception.cpp new file mode 100644 index 0000000000..d8cec57d3a --- /dev/null +++ b/test/module_init_exception.cpp @@ -0,0 +1,14 @@ +// 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 +#include + +using namespace boost::python; + +BOOST_PYTHON_MODULE(module_init_exception_ext) +{ + throw std::runtime_error("Module init failed"); +} diff --git a/test/module_init_exception.py b/test/module_init_exception.py new file mode 100644 index 0000000000..3da53e1956 --- /dev/null +++ b/test/module_init_exception.py @@ -0,0 +1,12 @@ +# 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...") + +try: + import module_init_exception_ext +except RuntimeError as e: + print(e) + +print("Done.") From f5d14ef15e98838b3cf18692d46c481287ed50d0 Mon Sep 17 00:00:00 2001 From: Dmitry Bely Date: Wed, 3 Feb 2021 13:52:14 +0300 Subject: [PATCH 047/120] Fix issue #280 --- src/module.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/module.cpp b/src/module.cpp index 9628481996..57675fa2df 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -21,7 +21,7 @@ namespace object m_obj(((borrowed_reference_t*)m)); scope current_module(m_obj); - handle_exception(init_function); + if (handle_exception(init_function)) return NULL; } return m; From aca3c80c4f80dd3d52219e1ee299e08bb980bcfd Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 24 Apr 2021 14:19:31 -0400 Subject: [PATCH 048/120] Respect alignment of by-value storage. --- .../converter/obj_mgr_arg_from_python.hpp | 4 +- .../converter/rvalue_from_python_data.hpp | 9 +++- .../converter/shared_ptr_from_python.hpp | 16 ++++--- .../boost/python/detail/referent_storage.hpp | 39 ++++------------ include/boost/python/instance_holder.hpp | 2 +- include/boost/python/object/instance.hpp | 11 ++--- include/boost/python/object/make_holder.hpp | 5 ++- include/boost/python/object/make_instance.hpp | 12 +++-- src/object/class.cpp | 38 ++++++++++++---- test/Jamfile | 1 + test/aligned_class.cpp | 33 ++++++++++++++ test/aligned_class.py | 44 +++++++++++++++++++ test/fabscript | 2 + 13 files changed, 158 insertions(+), 58 deletions(-) create mode 100644 test/aligned_class.cpp create mode 100755 test/aligned_class.py diff --git a/include/boost/python/converter/obj_mgr_arg_from_python.hpp b/include/boost/python/converter/obj_mgr_arg_from_python.hpp index cd4e1e0ea8..5132804082 100644 --- a/include/boost/python/converter/obj_mgr_arg_from_python.hpp +++ b/include/boost/python/converter/obj_mgr_arg_from_python.hpp @@ -81,9 +81,9 @@ inline object_manager_ref_arg_from_python::object_manager_ref_arg_from_pyth # if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 // needed for warning suppression python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x); - python::detail::construct_referent(&m_result.bytes, x_); + python::detail::construct_referent(m_result.bytes, x_); # else - python::detail::construct_referent(&m_result.bytes, (python::detail::borrowed_reference)x); + python::detail::construct_referent(m_result.bytes, (python::detail::borrowed_reference)x); # endif } diff --git a/include/boost/python/converter/rvalue_from_python_data.hpp b/include/boost/python/converter/rvalue_from_python_data.hpp index acb38f8498..d728681b3e 100644 --- a/include/boost/python/converter/rvalue_from_python_data.hpp +++ b/include/boost/python/converter/rvalue_from_python_data.hpp @@ -9,6 +9,7 @@ # include # include # include +# include # include # include @@ -132,7 +133,13 @@ template inline rvalue_from_python_data::~rvalue_from_python_data() { if (this->stage1.convertible == this->storage.bytes) - python::detail::destroy_referent(this->storage.bytes); + { + size_t allocated = sizeof(this->storage); + void *ptr = this->storage.bytes; + void *aligned_storage = + ::boost::alignment::align(boost::python::detail::alignment_of::value, 0, ptr, allocated); + python::detail::destroy_referent(aligned_storage); + } } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index bb2ae863ff..b5c62ba940 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -49,13 +49,17 @@ struct shared_ptr_from_python new (storage) SP(); else { - SP hold_convertible_ref_count( - (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); - // use aliasing constructor - new (storage) SP(hold_convertible_ref_count, - static_cast(data->convertible)); + void *const storage = ((converter::rvalue_from_python_storage >*)data)->storage.bytes; + // Deal with the "None" case. + if (data->convertible == source) + new (storage) SP(); + else + { + SP hold_convertible_ref_count((void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); + // use aliasing constructor + new (storage) SP(hold_convertible_ref_count, static_cast(data->convertible)); + } } - data->convertible = storage; } }; diff --git a/include/boost/python/detail/referent_storage.hpp b/include/boost/python/detail/referent_storage.hpp index 2cddf696d5..f646d2ae1d 100644 --- a/include/boost/python/detail/referent_storage.hpp +++ b/include/boost/python/detail/referent_storage.hpp @@ -5,39 +5,21 @@ #ifndef REFERENT_STORAGE_DWA200278_HPP # define REFERENT_STORAGE_DWA200278_HPP # include +# include # include namespace boost { namespace python { namespace detail { -struct alignment_dummy; -typedef void (*function_ptr)(); -typedef int (alignment_dummy::*member_ptr); -typedef int (alignment_dummy::*member_function_ptr)(); - -# define BOOST_PYTHON_ALIGNER(T, n) \ - typename mpl::if_c< \ - sizeof(T) <= size, T, char>::type t##n - -// Storage for size bytes, aligned to all fundamental types no larger than size -template -union aligned_storage +template +struct aligned_storage { - BOOST_PYTHON_ALIGNER(char, 0); - BOOST_PYTHON_ALIGNER(short, 1); - BOOST_PYTHON_ALIGNER(int, 2); - BOOST_PYTHON_ALIGNER(long, 3); - BOOST_PYTHON_ALIGNER(float, 4); - BOOST_PYTHON_ALIGNER(double, 5); - BOOST_PYTHON_ALIGNER(long double, 6); - BOOST_PYTHON_ALIGNER(void*, 7); - BOOST_PYTHON_ALIGNER(function_ptr, 8); - BOOST_PYTHON_ALIGNER(member_ptr, 9); - BOOST_PYTHON_ALIGNER(member_function_ptr, 10); + union type + { + typename ::boost::aligned_storage::type data; char bytes[size]; + }; }; - -# undef BOOST_PYTHON_ALIGNER - + // Compute the size of T's referent. We wouldn't need this at all, // but sizeof() is broken in CodeWarriors <= 8.0 template struct referent_size; @@ -50,15 +32,12 @@ union aligned_storage std::size_t, value = sizeof(T)); }; - // A metafunction returning a POD type which can store U, where T == // U&. If T is not a reference type, returns a POD which can store T. template struct referent_storage { - typedef aligned_storage< - ::boost::python::detail::referent_size::value - > type; + typedef typename aligned_storage::value, alignment_of::value>::type type; }; }}} // namespace boost::python::detail diff --git a/include/boost/python/instance_holder.hpp b/include/boost/python/instance_holder.hpp index 933f50d1a1..f4ed1e6608 100644 --- a/include/boost/python/instance_holder.hpp +++ b/include/boost/python/instance_holder.hpp @@ -38,7 +38,7 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable // Allocate storage for an object of the given size at the given // offset in the Python instance<> object if bytes are available // there. Otherwise allocate size bytes of heap memory. - static void* allocate(PyObject*, std::size_t offset, std::size_t size); + static void* allocate(PyObject*, std::size_t offset, std::size_t size, std::size_t alignment = 1); // Deallocate storage from the heap if it was not carved out of // the given Python object by allocate(), above. diff --git a/include/boost/python/object/instance.hpp b/include/boost/python/object/instance.hpp index 27b91a1e5f..ee4a6c5822 100644 --- a/include/boost/python/object/instance.hpp +++ b/include/boost/python/object/instance.hpp @@ -6,7 +6,7 @@ # define INSTANCE_DWA200295_HPP # include - +# include # include namespace boost { namespace python @@ -28,7 +28,7 @@ struct instance typedef typename boost::python::detail::type_with_alignment< boost::python::detail::alignment_of::value >::type align_t; - + union { align_t align; @@ -41,9 +41,10 @@ struct additional_instance_size { typedef instance instance_data; typedef instance instance_char; - BOOST_STATIC_CONSTANT( - std::size_t, value = sizeof(instance_data) - - BOOST_PYTHON_OFFSETOF(instance_char,storage)); + BOOST_STATIC_CONSTANT(std::size_t, + value = sizeof(instance_data) - + BOOST_PYTHON_OFFSETOF(instance_char,storage) + + boost::python::detail::alignment_of::value); }; }}} // namespace boost::python::object diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 0d54dd9f66..735e5395ca 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -89,8 +89,9 @@ struct make_holder BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a)) { typedef instance instance_t; - - void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder)); + + void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder), + boost::python::detail::alignment_of::value); try { (new (memory) Holder( p BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); diff --git a/include/boost/python/object/make_instance.hpp b/include/boost/python/object/make_instance.hpp index 5eb3aa9d9c..713fdc5ecd 100644 --- a/include/boost/python/object/make_instance.hpp +++ b/include/boost/python/object/make_instance.hpp @@ -43,11 +43,14 @@ struct make_instance_impl // construct the new C++ object and install the pointer // in the Python object. - Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result); + Holder *holder =Derived::construct(instance->storage.bytes, (PyObject*)instance, x); + holder->install(raw_result); // Note the position of the internally-stored Holder, // for the sake of destruction - Py_SET_SIZE(instance, offsetof(instance_t, storage)); + const size_t offset = reinterpret_cast(holder) - + reinterpret_cast(instance->storage.bytes) + offsetof(instance_t, storage); + Py_SET_SIZE(instance, offset); // Release ownership of the python object protect.cancel(); @@ -69,7 +72,10 @@ struct make_instance static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper x) { - return new (storage) Holder(instance, x); + size_t allocated = objects::additional_instance_size::value; + void* aligned_storage = ::boost::alignment::align(boost::python::detail::alignment_of::value, + sizeof(Holder), storage, allocated); + return new (aligned_storage) Holder(instance, x); } }; diff --git a/src/object/class.cpp b/src/object/class.cpp index c6bab76009..8778b7abcd 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -5,6 +5,7 @@ #include #include // #including this first is an intel6 workaround +#include #include #include @@ -721,28 +722,47 @@ namespace objects } // namespace objects -void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size) +typedef unsigned int alignment_marker_t; + +void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size, std::size_t alignment) { assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object)); objects::instance<>* self = (objects::instance<>*)self_; - int total_size_needed = holder_offset + holder_size; + int total_size_needed = holder_offset + holder_size + alignment - 1; if (-Py_SIZE(self) >= total_size_needed) { // holder_offset should at least point into the variable-sized part assert(holder_offset >= offsetof(objects::instance<>,storage)); + size_t allocated = holder_size + alignment; + void* storage = (char*)self + holder_offset; + void* aligned_storage = ::boost::alignment::align(alignment, holder_size, storage, allocated); + // Record the fact that the storage is occupied, noting where it starts - Py_SET_SIZE(self, holder_offset); - return (char*)self + holder_offset; + const size_t offset = reinterpret_cast(aligned_storage) - reinterpret_cast(storage) + holder_offset; + Py_SET_SIZE(self, offset); + return (char*)self + offset; } else { - void* const result = PyMem_Malloc(holder_size); - if (result == 0) + const size_t base_allocation = sizeof(alignment_marker_t) + holder_size + alignment - 1; + void* const base_storage = PyMem_Malloc(base_allocation); + if (base_storage == 0) throw std::bad_alloc(); - return result; + + const uintptr_t x = reinterpret_cast(base_storage) + sizeof(alignment_marker_t); + //this has problems for x -> max(void *) + //const size_t padding = alignment - ((x + sizeof(alignment_marker_t)) % alignment); + //only works for alignments with alignments of powers of 2, but no edge conditions + const uintptr_t padding = alignment == 1 ? 0 : ( alignment - (x & (alignment - 1)) ); + const size_t aligned_offset = sizeof(alignment_marker_t) + padding; + void* const aligned_storage = (char *)base_storage + aligned_offset; + BOOST_ASSERT((char *) aligned_storage + holder_size <= (char *)base_storage + base_allocation); + alignment_marker_t* const marker_storage = reinterpret_cast((char *)aligned_storage - sizeof(alignment_marker_t)); + *marker_storage = static_cast(padding); + return aligned_storage; } } @@ -752,7 +772,9 @@ void instance_holder::deallocate(PyObject* self_, void* storage) throw() objects::instance<>* self = (objects::instance<>*)self_; if (storage != (char*)self + Py_SIZE(self)) { - PyMem_Free(storage); + alignment_marker_t* marker_storage = reinterpret_cast((char *)storage - sizeof(alignment_marker_t)); + void *malloced_storage = (char *) storage - sizeof(alignment_marker_t) - (*marker_storage); + PyMem_Free(malloced_storage); } } diff --git a/test/Jamfile b/test/Jamfile index 9a5c756956..07cbd4c7e5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -132,6 +132,7 @@ bpl-test crossmod_exception [ bpl-test object ] [ bpl-test class ] +[ bpl-test aligned_class ] [ bpl-test list ] [ bpl-test long ] [ bpl-test dict ] diff --git a/test/aligned_class.cpp b/test/aligned_class.cpp new file mode 100644 index 0000000000..55f0fa3c70 --- /dev/null +++ b/test/aligned_class.cpp @@ -0,0 +1,33 @@ +// 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 +#include +#include +#include +#include +#include + +using namespace boost::python; + +struct BOOST_ALIGNMENT(32) X +{ + int x; + BOOST_ALIGNMENT(32) float f; + X(int n, float _f) : x(n), f(_f) + { + BOOST_ASSERT((reinterpret_cast(&f) % 32) == 0); + } +}; + +int x_function(X& x) { return x.x;} +float f_function(X& x) { return x.f;} + +BOOST_PYTHON_MODULE(aligned_class_ext) +{ + class_("X", init()); + def("x_function", x_function); + def("f_function", f_function); +} + +#include "module_tail.cpp" diff --git a/test/aligned_class.py b/test/aligned_class.py new file mode 100755 index 0000000000..eb27ac1e96 --- /dev/null +++ b/test/aligned_class.py @@ -0,0 +1,44 @@ +# 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 aligned_class_ext import * + +Ensure sanity: + + >>> x = X(42, 16) + >>> x_function(x) + 42 + >>> f_function(x) + 16.0 + +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, 16) + >>> x_function(x) + 42 + >>> f_function(x) + 16.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/test/fabscript b/test/fabscript index eb9379e0ac..d4d7ead83b 100644 --- a/test/fabscript +++ b/test/fabscript @@ -79,6 +79,8 @@ for t in [('injected',), ('callbacks',), ('defaults',), ('object',), + ('class',), + ('aligned_class',), ('list',), ('long',), ('dict',), From 2a82afdf6d30c28eb1775f3b8041d988f6f04598 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 27 Apr 2021 08:10:08 -0400 Subject: [PATCH 049/120] Upgrade base image & build prerequisites. --- .github/workflows/test-ubuntu.yml | 4 ++-- .github/workflows/test-windows.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 61a295981f..dab98aee4a 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -18,9 +18,9 @@ jobs: # pre-reqs installed, see: # https://github.com/teeks99/boost-python-test-docker - cxx: clang++ - docker-img: teeks99/boost-python-test:clang-11_1.66.0 + docker-img: teeks99/boost-python-test:clang-12_1.76.0 - cxx: g++ - docker-img: teeks99/boost-python-test:gcc-9_1.66.0 + docker-img: teeks99/boost-python-test:gcc-10_1.76.0 container: image: ${{ matrix.docker-img }} diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 4d5878ea7a..97761208cf 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -21,7 +21,7 @@ jobs: vcpkgGitCommitId: '8a9a97315aefb3f8bc5d81bf66ca0025938b9c91' vcpkgDirectory: '${{ runner.workspace }}/vcpkg' vcpkgTriplet: x64-windows - vcpkgArguments: boost-config boost-core boost-function boost-graph boost-iterator boost-lexical-cast boost-mpl boost-preprocessor boost-smart-ptr boost-static-assert + vcpkgArguments: boost-config boost-core boost-function boost-graph boost-iterator boost-lexical-cast boost-mpl boost-preprocessor boost-smart-ptr boost-static-assert boost-align - name: setup faber #shell: 'bash' From ecda18f01e252134090804d01219d90c7c1380c1 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Mon, 24 May 2021 22:14:55 +0300 Subject: [PATCH 050/120] Use the /python//numpy target instead of [ numpy.include ] (fixes #361) --- build/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Jamfile b/build/Jamfile index dbc9fb2036..03b69a25dd 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -117,7 +117,7 @@ lib boost_numpy BOOST_NUMPY_SOURCE [ cond [ python.numpy ] : /python//python_for_extensions ] [ unless [ python.numpy ] : no ] - $(numpy-include) + /python//numpy boost_python on:BOOST_DEBUG_PYTHON -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag From 5e77eabb6386854fd9456fee264de9742a485faa Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Wed, 26 May 2021 07:46:42 -0400 Subject: [PATCH 051/120] Revert previous commit until 'Boost.Build' is ready. --- build/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Jamfile b/build/Jamfile index 03b69a25dd..dbc9fb2036 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -117,7 +117,7 @@ lib boost_numpy BOOST_NUMPY_SOURCE [ cond [ python.numpy ] : /python//python_for_extensions ] [ unless [ python.numpy ] : no ] - /python//numpy + $(numpy-include) boost_python on:BOOST_DEBUG_PYTHON -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag From 209179fa093274ea447b7d95596dfde1f085ec0e Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 4 Jun 2021 03:10:21 +0300 Subject: [PATCH 052/120] Add CMakeLists.txt --- CMakeLists.txt | 176 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..299ef84e9c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,176 @@ +# Copyright 2020, 2021 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.14...3.20) + +project(boost_python VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +find_package(Python REQUIRED COMPONENTS Development OPTIONAL_COMPONENTS NumPy) + +if(Python_NumPy_FOUND) + message(STATUS "Boost.Python: using Python ${Python_VERSION} with NumPy at ${Python_NumPy_INCLUDE_DIRS}") +else() + message(STATUS "Boost.Python: using Python ${Python_VERSION} without NumPy") +endif() + +# boost_pythonXY + +set(_pyver ${Python_VERSION_MAJOR}${Python_VERSION_MINOR}) +set(_boost_python boost_python${_pyver}) + +add_library(${_boost_python} + src/dict.cpp + src/errors.cpp + src/exec.cpp + src/import.cpp + src/list.cpp + src/long.cpp + src/module.cpp + src/object_operators.cpp + src/object_protocol.cpp + src/slice.cpp + src/str.cpp + src/tuple.cpp + src/wrapper.cpp + src/converter/from_python.cpp + src/converter/registry.cpp + src/converter/type_id.cpp + src/converter/builtin_converters.cpp + src/converter/arg_to_python_base.cpp + src/object/enum.cpp + src/object/class.cpp + src/object/function.cpp + src/object/inheritance.cpp + src/object/life_support.cpp + src/object/pickle_support.cpp + src/object/iterator.cpp + src/object/stl_iterator.cpp + src/object_protocol.cpp + src/object_operators.cpp + src/object/function_doc_signature.cpp +) + +add_library(Boost::python${_pyver} ALIAS ${_boost_python}) + +target_include_directories(${_boost_python} PUBLIC include) + +target_link_libraries(${_boost_python} + PUBLIC + Boost::align + Boost::bind + Boost::config + Boost::conversion + Boost::core + Boost::detail + Boost::foreach + Boost::function + Boost::iterator + Boost::lexical_cast + Boost::mpl + Boost::numeric_conversion + Boost::preprocessor + Boost::smart_ptr + Boost::static_assert + Boost::tuple + Boost::type_traits + Boost::utility + + Python::Module + + PRIVATE + Boost::graph + Boost::integer + Boost::property_map +) + +target_compile_definitions(${_boost_python} + PUBLIC BOOST_PYTHON_NO_LIB + PRIVATE BOOST_PYTHON_SOURCE +) + +if(BUILD_SHARED_LIBS) + target_compile_definitions(${_boost_python} PUBLIC BOOST_PYTHON_DYN_LINK) +else() + target_compile_definitions(${_boost_python} PUBLIC BOOST_PYTHON_STATIC_LINK BOOST_PYTHON_STATIC_LIB) +endif() + +# Boost::python alias + +add_library(boost_python INTERFACE) +add_library(Boost::python ALIAS boost_python) +target_link_libraries(boost_python INTERFACE Boost::python${_pyver}) + +# Installation + +if(BOOST_SUPERPROJECT_VERSION AND NOT CMAKE_VERSION VERSION_LESS 3.13) + boost_install(TARGETS ${_boost_python} boost_python VERSION ${BOOST_SUPERPROJECT_VERSION} HEADER_DIRECTORY include) +endif() + +if(Python_NumPy_FOUND) + +# boost_numpyXY + +set(_boost_numpy boost_numpy${_pyver}) + +add_library(${_boost_numpy} + src/numpy/dtype.cpp + src/numpy/matrix.cpp + src/numpy/ndarray.cpp + src/numpy/numpy.cpp + src/numpy/scalars.cpp + src/numpy/ufunc.cpp +) + +add_library(Boost::numpy${_pyver} ALIAS ${_boost_numpy}) + +target_include_directories(${_boost_numpy} PUBLIC include) + +target_link_libraries(${_boost_numpy} + PUBLIC + Boost::config + Boost::core + Boost::detail + Boost::mpl + Boost::python + Boost::smart_ptr + + Python::NumPy +) + +target_compile_definitions(${_boost_numpy} + PUBLIC BOOST_NUMPY_NO_LIB + PRIVATE BOOST_NUMPY_SOURCE +) + +if(BUILD_SHARED_LIBS) + target_compile_definitions(${_boost_numpy} PUBLIC BOOST_NUMPY_DYN_LINK) +else() + target_compile_definitions(${_boost_numpy} PUBLIC BOOST_NUMPY_STATIC_LINK BOOST_NUMPY_STATIC_LIB) +endif() + +# Boost::numpy alias + +add_library(boost_numpy INTERFACE) +add_library(Boost::numpy ALIAS boost_numpy) +target_link_libraries(boost_numpy INTERFACE Boost::numpy${_pyver}) + +# Installation + +if(BOOST_SUPERPROJECT_VERSION AND NOT CMAKE_VERSION VERSION_LESS 3.13) + boost_install(TARGETS ${_boost_numpy} boost_numpy VERSION ${BOOST_SUPERPROJECT_VERSION}) +endif() + +endif() + +unset(_pyver) +unset(_boost_python) +unset(_boost_numpy) + +# Testing + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() From aee2667407736593bfbc81836e64d9d743d10481 Mon Sep 17 00:00:00 2001 From: TaWeiTu Date: Fri, 7 Aug 2020 14:30:12 +0800 Subject: [PATCH 053/120] Fix deprecated usage of Replace with and use namespace boost::placeholders when necessary. --- include/boost/python/exception_translator.hpp | 3 ++- include/boost/python/iterator.hpp | 3 ++- src/object/function.cpp | 2 +- src/object/inheritance.cpp | 3 ++- src/object/iterator.cpp | 2 +- test/import_.cpp | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/include/boost/python/exception_translator.hpp b/include/boost/python/exception_translator.hpp index 75ed0e1eec..1aa1465bdf 100644 --- a/include/boost/python/exception_translator.hpp +++ b/include/boost/python/exception_translator.hpp @@ -7,7 +7,7 @@ # include -# include +# include # include # include # include @@ -18,6 +18,7 @@ namespace boost { namespace python { template void register_exception_translator(Translate translate, boost::type* = 0) { + using namespace boost::placeholders; detail::register_exception_handler( boost::bind(detail::translate_exception(), _1, _2, translate) ); diff --git a/include/boost/python/iterator.hpp b/include/boost/python/iterator.hpp index 7c06ca2320..b0ea578959 100644 --- a/include/boost/python/iterator.hpp +++ b/include/boost/python/iterator.hpp @@ -22,7 +22,7 @@ works correctly. */ # pragma warning(disable: 4180) # endif -# include +# include # include namespace boost { namespace python { @@ -40,6 +40,7 @@ namespace detail , Target&(*)() ) { + using namespace boost::placeholders; return objects::make_iterator_function( boost::protect(boost::bind(get_start, _1)) , boost::protect(boost::bind(get_finish, _1)) diff --git a/src/object/function.cpp b/src/object/function.cpp index 787679e138..4adb49453c 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 7dc9db1cd7..a7b3156e41 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -184,6 +184,7 @@ namespace // map a type to a position in the index inline type_index_t::iterator type_position(class_id type) { + using namespace boost::placeholders; typedef index_entry entry; return std::lower_bound( diff --git a/src/object/iterator.cpp b/src/object/iterator.cpp index 3f6c4adacd..6b885a982c 100644 --- a/src/object/iterator.cpp +++ b/src/object/iterator.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include namespace boost { namespace python { namespace objects { diff --git a/test/import_.cpp b/test/import_.cpp index 3e21de0bad..8e03d9b448 100644 --- a/test/import_.cpp +++ b/test/import_.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include From 8dd151177374dbf0aa5cb86bd350cf1ad13e2160 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 4 Jul 2021 15:29:43 -0400 Subject: [PATCH 054/120] Use the /python//numpy target instead of [ numpy.include ] (fixes #361) --- build/Jamfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Jamfile b/build/Jamfile index dbc9fb2036..03b69a25dd 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -117,7 +117,7 @@ lib boost_numpy BOOST_NUMPY_SOURCE [ cond [ python.numpy ] : /python//python_for_extensions ] [ unless [ python.numpy ] : no ] - $(numpy-include) + /python//numpy boost_python on:BOOST_DEBUG_PYTHON -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag From a060d43bf2eb5dee702c75eb7aedf241cc426d14 Mon Sep 17 00:00:00 2001 From: Hajo Kirchhoff Date: Tue, 10 Aug 2021 13:23:18 +0200 Subject: [PATCH 055/120] -fix: boost::python::exec_file completely broken when PY_VERSION_HEX >= 0x03010000. Bug: char* f pointed to a temporary buffer returned by PyBytes_AsString. This buffer was released when Py_DECREF(fb) was called. As a result, f pointed to invalid memory when being passed to Py_RunFile. --- src/exec.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/exec.cpp b/src/exec.cpp index dd0c33103f..df1971691b 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -109,8 +109,8 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l PyObject *fo = Py_BuildValue("s", f); PyObject *fb = Py_None; PyUnicode_FSConverter(fo, &fb); - f = PyBytes_AsString(fb); - FILE *fs = fopen(f, "r"); + char *f_as_uft = PyBytes_AsString(fb); + FILE *fs = fopen(f_as_uft, "r"); Py_DECREF(fo); Py_DECREF(fb); #elif PY_VERSION_HEX >= 0x03000000 From f028aa407699d46b677ecc3cd72933c536aec98a Mon Sep 17 00:00:00 2001 From: Hajo Kirchhoff Date: Tue, 10 Aug 2021 13:26:02 +0200 Subject: [PATCH 056/120] -fix: issue #239 exec_file does not close the FILE handle. Note: Using FILE* is a bad choice here because of possible exceptions, but Py_RunFile is a C function. This fix works, because Py_RunFile - as a C function - does not throw exceptions. --- src/exec.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/exec.cpp b/src/exec.cpp index df1971691b..7488da1f6d 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -129,6 +129,7 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l f, Py_file_input, global.ptr(), local.ptr()); + fclose(fs); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); } From 41e208ecb598552f6d8c3bf9acacd5611d49a50d Mon Sep 17 00:00:00 2001 From: Denis Arnaud Date: Sun, 15 Aug 2021 17:05:31 +0200 Subject: [PATCH 057/120] Update call_method.hpp Was missing from https://github.com/boostorg/python/pull/320 I've tested it on one of my projects with (that patch on) Boost.Python/Boost 1.76.0 and it works well. Without that patch, there is a deprecation error. --- include/boost/python/call_method.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/python/call_method.hpp b/include/boost/python/call_method.hpp index 424077eab4..2f360791d7 100644 --- a/include/boost/python/call_method.hpp +++ b/include/boost/python/call_method.hpp @@ -59,7 +59,7 @@ call_method(PyObject* self, char const* name ) { PyObject* const result = - PyEval_CallMethod( + PyObject_CallMethod( self , const_cast(name) , const_cast("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") From a218babc8daee904a83f550fb66e5cb3f1cb3013 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 25 Apr 2022 10:51:46 +0200 Subject: [PATCH 058/120] Fix enum_type_object type on Python 3.11 The enum_type_object type inherits from PyLong_Type which is not tracked by the GC. Instances doesn't have to be tracked by the GC: remove the Py_TPFLAGS_HAVE_GC flag. The Python C API documentation says: "To create a container type, the tp_flags field of the type object must include the Py_TPFLAGS_HAVE_GC and provide an implementation of the tp_traverse handler." https://docs.python.org/dev/c-api/gcsupport.html The new exception was introduced in Python 3.11 by: https://github.com/python/cpython/issues/88429 --- src/object/enum.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 293e705899..5753b32e07 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -113,7 +113,6 @@ static PyTypeObject enum_type_object = { #if PY_VERSION_HEX < 0x03000000 | Py_TPFLAGS_CHECKTYPES #endif - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ From fdd3e8b2c1e06667386c4a23018d5ddb14e6b591 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 23 Aug 2022 23:03:03 -0400 Subject: [PATCH 059/120] Remove obsolete Jamfile --- build/Jamfile | 167 -------------------------------------------------- 1 file changed, 167 deletions(-) delete mode 100644 build/Jamfile diff --git a/build/Jamfile b/build/Jamfile deleted file mode 100644 index 03b69a25dd..0000000000 --- a/build/Jamfile +++ /dev/null @@ -1,167 +0,0 @@ -# Copyright David Abrahams 2001-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 os ; -import indirect ; -import modules ; -import feature ; -import property ; -import python ; - -if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] ) -{ - # Attempt default configuration of python - import toolset : using ; - using python ; -} - -if [ python.configured ] || ( --without-python in [ modules.peek : ARGV ] ) -{ - alias config-warning ; -} -else -{ - message config-warning - : "warning: No python installation configured and autoconfiguration" - : "note: failed. See http://www.boost.org/libs/python/doc/building.html" - : "note: for configuration instructions or pass --without-python to" - : "note: suppress this message and silently skip all Boost.Python targets" - ; -} - -project boost/python - : source-location ../src - ; - -rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } } -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 - : # sources - 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 - : # requirements - static:BOOST_PYTHON_STATIC_LIB - BOOST_PYTHON_SOURCE - - # On Windows, all code using Python has to link to the Python - # import library. - # - # On *nix we never link libboost_python to libpython. When - # extending Python, all Python symbols are provided by the - # Python interpreter executable. When embedding Python, the - # client executable is expected to explicitly link to - # /python//python (the target representing libpython) itself. - # - # python_for_extensions is a target defined by Boost.Build to - # provide the Python include paths, and on Windows, the Python - # import library, as usage requirements. - [ cond [ python.configured ] : /python//python_for_extensions ] - - # we prevent building when there is no python available - # as it's not possible anyway, and to cause dependents to - # fail to build - [ unless [ python.configured ] : no ] - config-warning - on:BOOST_DEBUG_PYTHON - -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @python-tag - @python.require-py - - : # default build - shared - : # usage requirements - static:BOOST_PYTHON_STATIC_LIB - on:BOOST_DEBUG_PYTHON - ; - -numpy-include = [ python.numpy-include ] ; -lib boost_numpy - : # sources - numpy/dtype.cpp - numpy/matrix.cpp - numpy/ndarray.cpp - numpy/numpy.cpp - numpy/scalars.cpp - numpy/ufunc.cpp - : # requirements - static:BOOST_NUMPY_STATIC_LIB - BOOST_NUMPY_SOURCE - [ cond [ python.numpy ] : /python//python_for_extensions ] - [ unless [ python.numpy ] : no ] - /python//numpy - boost_python - on:BOOST_DEBUG_PYTHON - -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @python-tag - @python.require-py - - : # default build - shared - : # usage requirements - static:BOOST_NUMPY_STATIC_LIB - on:BOOST_DEBUG_PYTHON - ; - -# boost-install creates `stage` and `install` targets -# -# `stage` stages (builds and copies into `stage/lib`) the given libraries -# `boost_python` and `boost_numpy` and their dependencies and is similar -# to issuing `b2 --with-python stage` from top level -# -# `install` installs the two libraries and their dependencies and is similar -# to issuing `b2 --with-python install` from top level - -if [ python.configured ] -{ - if [ python.numpy ] - { - boost-install boost_python boost_numpy ; - } - else - { - boost-install boost_python ; - } -} -else -{ - -# When Python isn't configured, the above `boost-install` is not executed, -# so we create empty `stage` and `install` targets that do nothing but issue -# a warning message unless `--without-python` is given - -alias stage : config-warning ; -explicit stage ; - -alias install : config-warning ; -explicit install ; - -} From 271bcea8bf8fc9a570bb68f7bbd33c538bce1e0e Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 23 Aug 2022 23:02:24 -0400 Subject: [PATCH 060/120] Don't attempt to deploy documentation from PRs. --- .github/workflows/deploy-documentation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-documentation.yml b/.github/workflows/deploy-documentation.yml index 83a0f08945..065945137b 100644 --- a/.github/workflows/deploy-documentation.yml +++ b/.github/workflows/deploy-documentation.yml @@ -1,6 +1,6 @@ name: deploy documentation -on: [push, pull_request] +on: [push] jobs: deploy: From 508da1d19890a2430a015a9192c94c848c38a8db Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 23 Aug 2022 09:28:23 -0400 Subject: [PATCH 061/120] Fix windows CI builds. --- .github/workflows/test-windows.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 97761208cf..36c4a8e4f0 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -15,16 +15,26 @@ jobs: - uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + - uses: microsoft/setup-msbuild@v1.1 - name: setup boost prerequisites uses: lukka/run-vcpkg@v6 with: - vcpkgGitCommitId: '8a9a97315aefb3f8bc5d81bf66ca0025938b9c91' + vcpkgGitCommitId: '88b1071e39f13b632644d9d953738d345a4ac055' vcpkgDirectory: '${{ runner.workspace }}/vcpkg' vcpkgTriplet: x64-windows - vcpkgArguments: boost-config boost-core boost-function boost-graph boost-iterator boost-lexical-cast boost-mpl boost-preprocessor boost-smart-ptr boost-static-assert boost-align - + vcpkgArguments: > + boost-config + boost-core + boost-function + boost-graph + boost-iterator + boost-lexical-cast + boost-mpl + boost-preprocessor + boost-smart-ptr + boost-static-assert + boost-align - name: setup faber - #shell: 'bash' run: | python -m pip install --upgrade pip python -m pip install setuptools faber numpy From 47d5bc76f69e20625214381c930a2fad5765e2b3 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Mon, 5 Sep 2022 20:54:11 -0400 Subject: [PATCH 062/120] Revert "Remove obsolete Jamfile" --- build/Jamfile | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 build/Jamfile diff --git a/build/Jamfile b/build/Jamfile new file mode 100644 index 0000000000..03b69a25dd --- /dev/null +++ b/build/Jamfile @@ -0,0 +1,167 @@ +# Copyright David Abrahams 2001-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 os ; +import indirect ; +import modules ; +import feature ; +import property ; +import python ; + +if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] ) +{ + # Attempt default configuration of python + import toolset : using ; + using python ; +} + +if [ python.configured ] || ( --without-python in [ modules.peek : ARGV ] ) +{ + alias config-warning ; +} +else +{ + message config-warning + : "warning: No python installation configured and autoconfiguration" + : "note: failed. See http://www.boost.org/libs/python/doc/building.html" + : "note: for configuration instructions or pass --without-python to" + : "note: suppress this message and silently skip all Boost.Python targets" + ; +} + +project boost/python + : source-location ../src + ; + +rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } } +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 + : # sources + 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 + : # requirements + static:BOOST_PYTHON_STATIC_LIB + BOOST_PYTHON_SOURCE + + # On Windows, all code using Python has to link to the Python + # import library. + # + # On *nix we never link libboost_python to libpython. When + # extending Python, all Python symbols are provided by the + # Python interpreter executable. When embedding Python, the + # client executable is expected to explicitly link to + # /python//python (the target representing libpython) itself. + # + # python_for_extensions is a target defined by Boost.Build to + # provide the Python include paths, and on Windows, the Python + # import library, as usage requirements. + [ cond [ python.configured ] : /python//python_for_extensions ] + + # we prevent building when there is no python available + # as it's not possible anyway, and to cause dependents to + # fail to build + [ unless [ python.configured ] : no ] + config-warning + on:BOOST_DEBUG_PYTHON + -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag + @python-tag + @python.require-py + + : # default build + shared + : # usage requirements + static:BOOST_PYTHON_STATIC_LIB + on:BOOST_DEBUG_PYTHON + ; + +numpy-include = [ python.numpy-include ] ; +lib boost_numpy + : # sources + numpy/dtype.cpp + numpy/matrix.cpp + numpy/ndarray.cpp + numpy/numpy.cpp + numpy/scalars.cpp + numpy/ufunc.cpp + : # requirements + static:BOOST_NUMPY_STATIC_LIB + BOOST_NUMPY_SOURCE + [ cond [ python.numpy ] : /python//python_for_extensions ] + [ unless [ python.numpy ] : no ] + /python//numpy + boost_python + on:BOOST_DEBUG_PYTHON + -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag + @python-tag + @python.require-py + + : # default build + shared + : # usage requirements + static:BOOST_NUMPY_STATIC_LIB + on:BOOST_DEBUG_PYTHON + ; + +# boost-install creates `stage` and `install` targets +# +# `stage` stages (builds and copies into `stage/lib`) the given libraries +# `boost_python` and `boost_numpy` and their dependencies and is similar +# to issuing `b2 --with-python stage` from top level +# +# `install` installs the two libraries and their dependencies and is similar +# to issuing `b2 --with-python install` from top level + +if [ python.configured ] +{ + if [ python.numpy ] + { + boost-install boost_python boost_numpy ; + } + else + { + boost-install boost_python ; + } +} +else +{ + +# When Python isn't configured, the above `boost-install` is not executed, +# so we create empty `stage` and `install` targets that do nothing but issue +# a warning message unless `--without-python` is given + +alias stage : config-warning ; +explicit stage ; + +alias install : config-warning ; +explicit install ; + +} From 6c3f3ecacf66f61d799d80294bbf59ceb84daf8a Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Fri, 22 Dec 2023 05:36:47 +0200 Subject: [PATCH 063/120] Normalize static/dynamic link macros and avoid redefinition warnings --- include/boost/python/detail/config.hpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 8dce9b742e..e2ac827040 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -57,9 +57,15 @@ ****************************************************************************/ // backwards compatibility: -#ifdef BOOST_PYTHON_STATIC_LIB -# define BOOST_PYTHON_STATIC_LINK -# elif !defined(BOOST_PYTHON_DYNAMIC_LIB) +#if defined(BOOST_PYTHON_STATIC_LINK) && !defined(BOOST_PYTHON_STATIC_LIB) +# define BOOST_PYTHON_STATIC_LIB +#endif + +#if defined(BOOST_PYTHON_DYNAMIC_LINK) && !defined(BOOST_PYTHON_DYNAMIC_LIB) +# define BOOST_PYTHON_DYNAMIC_LIB +#endif + +#if !defined(BOOST_PYTHON_STATIC_LIB) && !defined(BOOST_PYTHON_DYNAMIC_LIB) # define BOOST_PYTHON_DYNAMIC_LIB #endif From 0474de0f6cc9c6e7230aeb7164af2f7e4ccf74bf Mon Sep 17 00:00:00 2001 From: Alexis DUBURCQ Date: Fri, 15 Mar 2024 14:10:16 +0100 Subject: [PATCH 064/120] Support numpy 2.0.0b1 --- src/numpy/dtype.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/numpy/dtype.cpp b/src/numpy/dtype.cpp index 88a20a27b5..da30d1927b 100644 --- a/src/numpy/dtype.cpp +++ b/src/numpy/dtype.cpp @@ -98,7 +98,13 @@ python::detail::new_reference dtype::convert(object const & arg, bool align) return python::detail::new_reference(reinterpret_cast(obj)); } -int dtype::get_itemsize() const { return reinterpret_cast(ptr())->elsize;} +int dtype::get_itemsize() const { +#if NPY_ABI_VERSION < 0x02000000 + return reinterpret_cast(ptr())->elsize; +#else + return PyDataType_ELSIZE(reinterpret_cast(ptr())); +#endif +} bool equivalent(dtype const & a, dtype const & b) { // On Windows x64, the behaviour described on From 1fed0824ad95f6f993c931ed4616f7549996e231 Mon Sep 17 00:00:00 2001 From: Konstantin Podsvirov Date: Sat, 3 Dec 2022 19:21:21 +0300 Subject: [PATCH 065/120] Fix typo in numpy tutorial --- doc/numpy/tutorial/dtype.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/numpy/tutorial/dtype.rst b/doc/numpy/tutorial/dtype.rst index 557e72ba2d..9bea646a65 100644 --- a/doc/numpy/tutorial/dtype.rst +++ b/doc/numpy/tutorial/dtype.rst @@ -48,7 +48,7 @@ Next, create a list, and add this tuple to the list. Then use the list to create list_for_dtype.append(for_custom_dtype) ; np::dtype custom_dtype = np::dtype(list_for_dtype) ; -We are now ready to create an ndarray with dimensions specified by \*shape\* and of custom dtpye :: +We are now ready to create an ndarray with dimensions specified by \*shape\* and of custom dtype :: np::ndarray new_array = np::zeros(shape,custom_dtype); } From 99a5352b5cf790c559a7b976c1ba99520431d9d1 Mon Sep 17 00:00:00 2001 From: "Billy K. Poon" Date: Mon, 15 Jul 2024 15:48:38 -0700 Subject: [PATCH 066/120] Another fix for numpy 2.0 - Compare pointers directly instead of using PyArray_EquivTypes --- src/numpy/dtype.cpp | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/src/numpy/dtype.cpp b/src/numpy/dtype.cpp index da30d1927b..1ce8c6ec32 100644 --- a/src/numpy/dtype.cpp +++ b/src/numpy/dtype.cpp @@ -107,32 +107,7 @@ int dtype::get_itemsize() const { } bool equivalent(dtype const & a, dtype const & b) { - // On Windows x64, the behaviour described on - // http://docs.scipy.org/doc/numpy/reference/c-api.array.html for - // PyArray_EquivTypes unfortunately does not extend as expected: - // "For example, on 32-bit platforms, NPY_LONG and NPY_INT are equivalent". - // This should also hold for 64-bit platforms (and does on Linux), but not - // on Windows. Implement an alternative: -#ifdef _MSC_VER - if (sizeof(long) == sizeof(int) && - // Manually take care of the type equivalence. - ((a == dtype::get_builtin() || a == dtype::get_builtin()) && - (b == dtype::get_builtin() || b == dtype::get_builtin()) || - (a == dtype::get_builtin() || a == dtype::get_builtin()) && - (b == dtype::get_builtin() || b == dtype::get_builtin()))) { - return true; - } else { - return PyArray_EquivTypes( - reinterpret_cast(a.ptr()), - reinterpret_cast(b.ptr()) - ); - } -#else - return PyArray_EquivTypes( - reinterpret_cast(a.ptr()), - reinterpret_cast(b.ptr()) - ); -#endif + return a == b; } namespace From f6d20e1099fbc6df41a037594a67300b22070812 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Mon, 11 Mar 2024 08:38:16 -0500 Subject: [PATCH 067/120] Make the library modular usable. --- build.jam | 42 ++++++++++++++++++++++++++++++++ build/Jamfile | 61 ++++++++++++++++++++++------------------------- example/README.md | 2 +- test/Jamfile | 8 ++++--- 4 files changed, 76 insertions(+), 37 deletions(-) create mode 100644 build.jam diff --git a/build.jam b/build.jam new file mode 100644 index 0000000000..f5bd099742 --- /dev/null +++ b/build.jam @@ -0,0 +1,42 @@ +# Copyright René Ferdinand Rivera Morell 2024 +# 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 project ; + +project /boost/python + : common-requirements + /boost/align//boost_align + /boost/bind//boost_bind + /boost/config//boost_config + /boost/conversion//boost_conversion + /boost/core//boost_core + /boost/detail//boost_detail + /boost/foreach//boost_foreach + /boost/function//boost_function + /boost/graph//boost_graph + /boost/integer//boost_integer + /boost/iterator//boost_iterator + /boost/lexical_cast//boost_lexical_cast + /boost/mpl//boost_mpl + /boost/numeric_conversion//boost_numeric_conversion + /boost/preprocessor//boost_preprocessor + /boost/property_map//boost_property_map + /boost/smart_ptr//boost_smart_ptr + /boost/static_assert//boost_static_assert + /boost/tuple//boost_tuple + /boost/type_traits//boost_type_traits + /boost/utility//boost_utility + include + ; + +explicit + [ alias boost_python : build//boost_python ] + [ alias boost_numpy : build//boost_numpy ] + [ alias all : boost_python boost_numpy test ] + ; + +call-if : boost-library python + : install boost_python boost_numpy + ; diff --git a/build/Jamfile b/build/Jamfile index 03b69a25dd..d85c165baf 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -30,7 +30,7 @@ else ; } -project boost/python +project : source-location ../src ; @@ -38,6 +38,17 @@ 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 ; } } +rule tag ( name : type ? : property-set ) +{ + if python-tag in [ RULENAMES $(__name__) ] + { + return [ $(__name__).python-tag $(name) : $(type) : $(property-set) ] ; + } +} + +if [ python.configured ] +{ + lib boost_python : # sources list.cpp @@ -92,8 +103,8 @@ lib boost_python [ unless [ python.configured ] : no ] config-warning on:BOOST_DEBUG_PYTHON - -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @python-tag + -@%boostcpp.tag + @tag @python.require-py : # default build @@ -103,6 +114,17 @@ lib boost_python on:BOOST_DEBUG_PYTHON ; +} +else +{ + +alias boost_python : config-warning ; + +} + +if [ python.configured ] && [ python.numpy ] +{ + numpy-include = [ python.numpy-include ] ; lib boost_numpy : # sources @@ -120,8 +142,8 @@ lib boost_numpy /python//numpy boost_python on:BOOST_DEBUG_PYTHON - -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @python-tag + -@%boostcpp.tag + @tag @python.require-py : # default build @@ -131,37 +153,10 @@ lib boost_numpy on:BOOST_DEBUG_PYTHON ; -# boost-install creates `stage` and `install` targets -# -# `stage` stages (builds and copies into `stage/lib`) the given libraries -# `boost_python` and `boost_numpy` and their dependencies and is similar -# to issuing `b2 --with-python stage` from top level -# -# `install` installs the two libraries and their dependencies and is similar -# to issuing `b2 --with-python install` from top level - -if [ python.configured ] -{ - if [ python.numpy ] - { - boost-install boost_python boost_numpy ; - } - else - { - boost-install boost_python ; - } } else { -# When Python isn't configured, the above `boost-install` is not executed, -# so we create empty `stage` and `install` targets that do nothing but issue -# a warning message unless `--without-python` is given - -alias stage : config-warning ; -explicit stage ; - -alias install : config-warning ; -explicit install ; +alias boost_numpy : config-warning ; } diff --git a/example/README.md b/example/README.md index b090cbe1e3..af03f20ba8 100644 --- a/example/README.md +++ b/example/README.md @@ -3,7 +3,7 @@ # Examples This directory contains various examples using Boost.Python. -You may compile these using the `bjam` command either in this directory +You may compile these using the `b2` command either in this directory or in any of the subdirectories. You may need to adjust the paths in the Jamroot file if Boost.Python is not installed in a default location. diff --git a/test/Jamfile b/test/Jamfile index 07cbd4c7e5..48e57487f5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -2,14 +2,16 @@ # Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +require-b2 5.0.1 ; +import-search /boost/config/checks ; + import python ; import os ; -import ../../config/checks/config : requires ; +import config : requires ; lib socket ; -use-project /boost/python : ../build ; -project /boost/python/test +project : requirements gcc:-Wextra qnxnto:socket From d8d9861036eed75918fe50d72cad98a4c7f3160d Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 17 Mar 2024 18:33:44 -0500 Subject: [PATCH 068/120] Put back removing qualified boostcpp tag. As we need it until the Jamroot removes the qualified tag. --- build/Jamfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/Jamfile b/build/Jamfile index d85c165baf..64843288ae 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -104,6 +104,7 @@ lib boost_python config-warning on:BOOST_DEBUG_PYTHON -@%boostcpp.tag + -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag @tag @python.require-py @@ -143,6 +144,7 @@ lib boost_numpy boost_python on:BOOST_DEBUG_PYTHON -@%boostcpp.tag + -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag @tag @python.require-py From 071b0bc964323f2f3eb1cee1624f2a3e00679071 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 29 Mar 2024 21:15:59 -0500 Subject: [PATCH 069/120] Switch to library requirements instead of source. As source puts extra source in install targets. --- build.jam | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/build.jam b/build.jam index f5bd099742..d03ca41b11 100644 --- a/build.jam +++ b/build.jam @@ -7,27 +7,27 @@ import project ; project /boost/python : common-requirements - /boost/align//boost_align - /boost/bind//boost_bind - /boost/config//boost_config - /boost/conversion//boost_conversion - /boost/core//boost_core - /boost/detail//boost_detail - /boost/foreach//boost_foreach - /boost/function//boost_function - /boost/graph//boost_graph - /boost/integer//boost_integer - /boost/iterator//boost_iterator - /boost/lexical_cast//boost_lexical_cast - /boost/mpl//boost_mpl - /boost/numeric_conversion//boost_numeric_conversion - /boost/preprocessor//boost_preprocessor - /boost/property_map//boost_property_map - /boost/smart_ptr//boost_smart_ptr - /boost/static_assert//boost_static_assert - /boost/tuple//boost_tuple - /boost/type_traits//boost_type_traits - /boost/utility//boost_utility + /boost/align//boost_align + /boost/bind//boost_bind + /boost/config//boost_config + /boost/conversion//boost_conversion + /boost/core//boost_core + /boost/detail//boost_detail + /boost/foreach//boost_foreach + /boost/function//boost_function + /boost/graph//boost_graph + /boost/integer//boost_integer + /boost/iterator//boost_iterator + /boost/lexical_cast//boost_lexical_cast + /boost/mpl//boost_mpl + /boost/numeric_conversion//boost_numeric_conversion + /boost/preprocessor//boost_preprocessor + /boost/property_map//boost_property_map + /boost/smart_ptr//boost_smart_ptr + /boost/static_assert//boost_static_assert + /boost/tuple//boost_tuple + /boost/type_traits//boost_type_traits + /boost/utility//boost_utility include ; From 9ab1742c465ae08aacf79edd922c7e4989437442 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 28 Apr 2024 20:16:29 -0500 Subject: [PATCH 070/120] Add missing NO_LIB usage requirements. --- build/Jamfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/Jamfile b/build/Jamfile index 64843288ae..76042bb12a 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -113,6 +113,7 @@ lib boost_python : # usage requirements static:BOOST_PYTHON_STATIC_LIB on:BOOST_DEBUG_PYTHON + BOOST_PYTHON_NO_LIB ; } @@ -153,6 +154,7 @@ lib boost_numpy : # usage requirements static:BOOST_NUMPY_STATIC_LIB on:BOOST_DEBUG_PYTHON + BOOST_NUMPY_NO_LIB ; } From 06fa956fe83a0d44d143c45d92d67bd00c3d91aa Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sun, 5 May 2024 09:00:01 -0500 Subject: [PATCH 071/120] Add requires-b2 check to top-level build file. --- build.jam | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.jam b/build.jam index d03ca41b11..dbd0f1ffa5 100644 --- a/build.jam +++ b/build.jam @@ -3,6 +3,8 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +require-b2 5.1 ; + import project ; project /boost/python From 5a07cdb96bba9a310106094a7f1aa262a006700b Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 14 Jun 2024 11:33:56 -0500 Subject: [PATCH 072/120] Bump B2 require to 5.2 --- build.jam | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build.jam b/build.jam index dbd0f1ffa5..77aea7b462 100644 --- a/build.jam +++ b/build.jam @@ -3,9 +3,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) -require-b2 5.1 ; - -import project ; +require-b2 5.2 ; project /boost/python : common-requirements From 30bdbf3ae2097e0ae8f3887589b1136373875511 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Tue, 23 Jul 2024 22:34:22 -0500 Subject: [PATCH 073/120] Move inter-lib dependencies to a project variable and into the build targets. --- build.jam | 45 ++++++++++++++++++++++++--------------------- build/Jamfile | 1 + 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/build.jam b/build.jam index 77aea7b462..7adb65de6b 100644 --- a/build.jam +++ b/build.jam @@ -5,29 +5,31 @@ require-b2 5.2 ; +constant boost_dependencies : + /boost/align//boost_align + /boost/bind//boost_bind + /boost/config//boost_config + /boost/conversion//boost_conversion + /boost/core//boost_core + /boost/detail//boost_detail + /boost/foreach//boost_foreach + /boost/function//boost_function + /boost/graph//boost_graph + /boost/integer//boost_integer + /boost/iterator//boost_iterator + /boost/lexical_cast//boost_lexical_cast + /boost/mpl//boost_mpl + /boost/numeric_conversion//boost_numeric_conversion + /boost/preprocessor//boost_preprocessor + /boost/property_map//boost_property_map + /boost/smart_ptr//boost_smart_ptr + /boost/static_assert//boost_static_assert + /boost/tuple//boost_tuple + /boost/type_traits//boost_type_traits + /boost/utility//boost_utility ; + project /boost/python : common-requirements - /boost/align//boost_align - /boost/bind//boost_bind - /boost/config//boost_config - /boost/conversion//boost_conversion - /boost/core//boost_core - /boost/detail//boost_detail - /boost/foreach//boost_foreach - /boost/function//boost_function - /boost/graph//boost_graph - /boost/integer//boost_integer - /boost/iterator//boost_iterator - /boost/lexical_cast//boost_lexical_cast - /boost/mpl//boost_mpl - /boost/numeric_conversion//boost_numeric_conversion - /boost/preprocessor//boost_preprocessor - /boost/property_map//boost_property_map - /boost/smart_ptr//boost_smart_ptr - /boost/static_assert//boost_static_assert - /boost/tuple//boost_tuple - /boost/type_traits//boost_type_traits - /boost/utility//boost_utility include ; @@ -40,3 +42,4 @@ explicit call-if : boost-library python : install boost_python boost_numpy ; + diff --git a/build/Jamfile b/build/Jamfile index 76042bb12a..dfc1e92d63 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -32,6 +32,7 @@ else project : source-location ../src + : common-requirements $(boost_dependencies) ; rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } } From 5a8d09613581f771fe272cead39e0cee7d41fd66 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Fri, 26 Jul 2024 17:39:24 -0500 Subject: [PATCH 074/120] Split b2 dependencies into public and private. --- build.jam | 4 ---- build/Jamfile | 8 ++++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/build.jam b/build.jam index 7adb65de6b..e9eb1a11a2 100644 --- a/build.jam +++ b/build.jam @@ -14,15 +14,11 @@ constant boost_dependencies : /boost/detail//boost_detail /boost/foreach//boost_foreach /boost/function//boost_function - /boost/graph//boost_graph - /boost/integer//boost_integer /boost/iterator//boost_iterator /boost/lexical_cast//boost_lexical_cast /boost/mpl//boost_mpl /boost/numeric_conversion//boost_numeric_conversion /boost/preprocessor//boost_preprocessor - /boost/property_map//boost_property_map - /boost/smart_ptr//boost_smart_ptr /boost/static_assert//boost_static_assert /boost/tuple//boost_tuple /boost/type_traits//boost_type_traits diff --git a/build/Jamfile b/build/Jamfile index dfc1e92d63..c8f9859c64 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -30,9 +30,17 @@ else ; } +constant boost_dependencies_private : + /boost/graph//boost_graph + /boost/integer//boost_integer + /boost/property_map//boost_property_map + /boost/smart_ptr//boost_smart_ptr + ; + project : source-location ../src : common-requirements $(boost_dependencies) + : requirements $(boost_dependencies_private) ; rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } } From 8ca8724ad9eafb5a07a437fb0a676235f1c1cdec Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Wed, 7 Aug 2024 23:28:26 -0500 Subject: [PATCH 075/120] Update build deps. --- test/Jamfile | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/test/Jamfile b/test/Jamfile index 48e57487f5..40115d86cb 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -30,7 +30,7 @@ rule py-run ( sources * : input-file ? ) : $(input-file) : #requirements BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION - + ] ; } @@ -54,6 +54,18 @@ rule require-windows ( properties * ) if [ python.configured ] { +alias base_deps : usage-requirements + /boost/align//boost_align + /boost/assert//boost_assert + /boost/config//boost_config + /boost/core//boost_core + /boost/detail//boost_detail + /boost/function//boost_function + /boost/mpl//boost_mpl + /boost/preprocessor//boost_preprocessor + /boost/static_assert//boost_static_assert + /boost/type_traits//boost_type_traits + ; test-suite python : @@ -99,8 +111,8 @@ bpl-test crossmod_exception [ bpl-test andreas_beyer ] [ bpl-test wrapper_held_type ] -[ bpl-test polymorphism2_auto_ptr - : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp +[ bpl-test polymorphism2_auto_ptr + : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp : [ requires auto_ptr ] ] @@ -121,7 +133,7 @@ bpl-test crossmod_exception [ 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 ] @@ -194,13 +206,13 @@ bpl-test crossmod_opaque # Whenever the cause for the failure of the polymorphism test is found # and fixed, this should be retested. hp_cxx: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 +[ 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) @@ -214,28 +226,29 @@ bpl-test crossmod_opaque # --- unit tests of library components --- -[ compile indirect_traits_test.cpp ] -[ run destroy_test.cpp ] +[ compile indirect_traits_test.cpp : base_deps ] +[ run destroy_test.cpp : : : base_deps ] [ py-run pointer_type_id_test.cpp ] [ py-run bases.cpp ] -[ run if_else.cpp ] +[ run if_else.cpp : : : base_deps ] [ py-run pointee.cpp ] -[ run result.cpp ] +[ run result.cpp : : : base_deps ] -[ compile string_literal.cpp ] +[ compile string_literal.cpp : base_deps ] [ 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 - : + +[ run select_from_python_test.cpp ../src/converter/type_id.cpp + : : : BOOST_PYTHON_STATIC_LIB $(PY) + base_deps ] From 58b1a010bb49f9709af0835eada5a474841b956e Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Fri, 21 Apr 2023 17:16:41 +0200 Subject: [PATCH 076/120] Set __qualname__ for Python >= 3.3 --- src/object/class.cpp | 13 +++++++++++++ test/nested.py | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index 8778b7abcd..5b5095151d 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -502,6 +502,16 @@ namespace objects ); } + str qualname(const char *name) + { +#if PY_VERSION_HEX >= 0x03030000 + if (PyObject_HasAttrString(scope().ptr(), "__qualname__")) { + return str("%s.%s" % make_tuple(scope().attr("__qualname__"), name)); + } +#endif + return str(name); + } + namespace { // Find a registered class object corresponding to id. Return a @@ -564,6 +574,9 @@ namespace objects object m = module_prefix(); if (m) d["__module__"] = m; +#if PY_VERSION_HEX >= 0x03030000 + d["__qualname__"] = qualname(name); +#endif if (doc != 0) d["__doc__"] = doc; diff --git a/test/nested.py b/test/nested.py index 720790173c..56f81e5269 100644 --- a/test/nested.py +++ b/test/nested.py @@ -14,7 +14,7 @@ 'X' >>> X.Y - + >>> X.Y.__module__ 'nested_ext' From 7a3cc070423a4cba35b5d2585cd680349c84387a Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Mon, 24 Apr 2023 11:14:55 +0200 Subject: [PATCH 077/120] Emit qualfied names in docstrings --- .../boost/python/object/function_doc_signature.hpp | 2 +- src/object/function_doc_signature.cpp | 13 +++++++++---- test/nested.cpp | 7 +++++++ test/nested.py | 3 +++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/boost/python/object/function_doc_signature.hpp b/include/boost/python/object/function_doc_signature.hpp index 4f00cb385a..5fa2c19dd5 100644 --- a/include/boost/python/object/function_doc_signature.hpp +++ b/include/boost/python/object/function_doc_signature.hpp @@ -18,7 +18,7 @@ namespace boost { namespace python { namespace objects { class function_doc_signature_generator{ - static const char * py_type_str(const python::detail::signature_element &s); + static str py_type_str(const python::detail::signature_element &s); static bool arity_cmp( function const *f1, function const *f2 ); static bool are_seq_overloads( function const *f1, function const *f2 , bool check_docs); static std::vector flatten(function const *f); diff --git a/src/object/function_doc_signature.cpp b/src/object/function_doc_signature.cpp index 41695285ac..c5a5498846 100644 --- a/src/object/function_doc_signature.cpp +++ b/src/object/function_doc_signature.cpp @@ -114,19 +114,24 @@ namespace boost { namespace python { namespace objects { return res; } - const char * function_doc_signature_generator::py_type_str(const python::detail::signature_element &s) + str function_doc_signature_generator::py_type_str(const python::detail::signature_element &s) { if (s.basename==std::string("void")){ static const char * none = "None"; - return none; + return str(none); } PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0; +#if PY_VERSION_HEX < 0x03030000 if ( py_type ) - return py_type->tp_name; + return str(py_type->tp_name); +#else + if ( py_type && (py_type->tp_flags & Py_TPFLAGS_HEAPTYPE) ) + return str(handle<>(borrowed(((PyHeapTypeObject*)(py_type))->ht_qualname))); +#endif else{ static const char * object = "object"; - return object; + return str(object); } } diff --git a/test/nested.cpp b/test/nested.cpp index de656d2b8b..b807c8bdb9 100644 --- a/test/nested.cpp +++ b/test/nested.cpp @@ -4,6 +4,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include #include +#include #include #include #include "test_class.hpp" @@ -26,11 +27,13 @@ std::ostream& operator<<(std::ostream& s, Y const& x) return s << x.value(); } +void test_function(const X& x, const Y& y) {} BOOST_PYTHON_MODULE(nested_ext) { using namespace boost::python; + { // Establish X as the current scope. scope x_class = class_("X", init()) @@ -42,6 +45,10 @@ BOOST_PYTHON_MODULE(nested_ext) class_("Y", init()) .def(str(self)) ; + } + + // The generated docstring will use the fully-qualified name of Y + def("test_function", &test_function); } diff --git a/test/nested.py b/test/nested.py index 56f81e5269..3d97208b77 100644 --- a/test/nested.py +++ b/test/nested.py @@ -21,6 +21,9 @@ >>> X.Y.__name__ 'Y' + + >>> test_function.__doc__.strip().split('\\n')[0] + 'test_function( (X)arg1, (X.Y)arg2) -> None :' ''' From a498e2458c3ee697176790b6163c6df539f7e62e Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Tue, 25 Apr 2023 15:46:28 +0200 Subject: [PATCH 078/120] Qualify types defined in other modules --- include/boost/python/object/function.hpp | 3 ++ .../python/object/function_doc_signature.hpp | 4 +- src/object/function.cpp | 17 ++++++- src/object/function_doc_signature.cpp | 47 +++++++++++++------ 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index f29d344820..b1a1676b63 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -42,6 +42,8 @@ struct BOOST_PYTHON_DECL function : PyObject object const& get_namespace() const { return m_namespace; } + object const& get_module() const { return m_module; } + private: // helper functions object signature(bool show_return_type=false) const; object signatures(bool show_return_type=false) const; @@ -53,6 +55,7 @@ struct BOOST_PYTHON_DECL function : PyObject handle m_overloads; object m_name; object m_namespace; + object m_module; object m_doc; object m_arg_names; unsigned m_nkeyword_values; diff --git a/include/boost/python/object/function_doc_signature.hpp b/include/boost/python/object/function_doc_signature.hpp index 5fa2c19dd5..91c90895ca 100644 --- a/include/boost/python/object/function_doc_signature.hpp +++ b/include/boost/python/object/function_doc_signature.hpp @@ -18,13 +18,13 @@ namespace boost { namespace python { namespace objects { class function_doc_signature_generator{ - static str py_type_str(const python::detail::signature_element &s); + static str py_type_str(const python::detail::signature_element &s, const object& current_module_name); static bool arity_cmp( function const *f1, function const *f2 ); static bool are_seq_overloads( function const *f1, function const *f2 , bool check_docs); static std::vector flatten(function const *f); static std::vector split_seq_overloads( const std::vector &funcs, bool split_on_doc_change); static str raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); - static str parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types); + static str parameter_string(py_function const &f, size_t n, object arg_names, const object& module_name, bool cpp_types); static str pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); public: diff --git a/src/object/function.cpp b/src/object/function.cpp index 4adb49453c..a220befd5b 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -489,11 +489,24 @@ void function::add_to_namespace( assert(!PyErr_Occurred()); handle<> name_space_name( - allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast("__name__")))); + allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast( +#if PY_VERSION_HEX < 0x03030000 + "__name__" +#else + "__qualname__" +#endif + )))); PyErr_Clear(); if (name_space_name) new_func->m_namespace = object(name_space_name); + + object module_name( + PyObject_IsInstance(name_space.ptr(), upcast(&PyModule_Type)) + ? object(name_space.attr("__name__")) + : api::getattr(name_space, "__module__", str()) + ); + new_func->m_module = module_name; } if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) @@ -670,7 +683,7 @@ extern "C" static PyObject* function_get_module(PyObject* op, void*) { function* f = downcast(op); - object const& ns = f->get_namespace(); + object const& ns = f->get_module(); if (!ns.is_none()) { return python::incref(ns.ptr()); } diff --git a/src/object/function_doc_signature.cpp b/src/object/function_doc_signature.cpp index c5a5498846..18d458698d 100644 --- a/src/object/function_doc_signature.cpp +++ b/src/object/function_doc_signature.cpp @@ -114,7 +114,16 @@ namespace boost { namespace python { namespace objects { return res; } - str function_doc_signature_generator::py_type_str(const python::detail::signature_element &s) + static str get_qualname(const PyTypeObject *py_type) + { +# if PY_VERSION_HEX >= 0x03030000 + if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) + return str(handle<>(borrowed(((PyHeapTypeObject*)(py_type))->ht_qualname))); +# endif + return str(py_type->tp_name); + } + + str function_doc_signature_generator::py_type_str(const python::detail::signature_element &s, const object ¤t_module_name) { if (s.basename==std::string("void")){ static const char * none = "None"; @@ -122,20 +131,30 @@ namespace boost { namespace python { namespace objects { } PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0; -#if PY_VERSION_HEX < 0x03030000 - if ( py_type ) - return str(py_type->tp_name); -#else - if ( py_type && (py_type->tp_flags & Py_TPFLAGS_HEAPTYPE) ) - return str(handle<>(borrowed(((PyHeapTypeObject*)(py_type))->ht_qualname))); -#endif - else{ + if ( py_type ) { + str name(get_qualname(py_type)); + if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) { + // Qualify the type name if it is defined in a different module. + PyObject *type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__"); + if ( + type_module_name + && PyObject_RichCompareBool( + type_module_name, + current_module_name.ptr(), + Py_NE + ) != 0 + ) { + return str("%s.%s" % make_tuple(handle<>(borrowed(type_module_name)), name)); + } + } + return name; + } else { static const char * object = "object"; return str(object); } } - str function_doc_signature_generator::parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types) + str function_doc_signature_generator::parameter_string(py_function const &f, size_t n, object arg_names, const object& current_module_name, bool cpp_types) { str param; @@ -161,12 +180,12 @@ namespace boost { namespace python { namespace objects { { object kv; if ( arg_names && (kv = arg_names[n-1]) ) - param = str( " (%s)%s" % make_tuple(py_type_str(s[n]),kv[0]) ); + param = str( " (%s)%s" % make_tuple(py_type_str(s[n], current_module_name),kv[0]) ); else - param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n]),"arg", n) ); + param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n], current_module_name),"arg", n) ); } else //we are processing the return type - param = py_type_str(f.get_return_type()); + param = py_type_str(f.get_return_type(), current_module_name); } //an argument - check for default value and append it @@ -204,7 +223,7 @@ namespace boost { namespace python { namespace objects { str param; formal_params.append( - parameter_string(impl, n, f->m_arg_names, cpp_types) + parameter_string(impl, n, f->m_arg_names, f->get_module(), cpp_types) ); // find all the arguments with default values preceeding the arity-n_overloads From c4e3b13dc2cf510d9824474da9435644ce821c62 Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Tue, 25 Apr 2023 16:29:12 +0200 Subject: [PATCH 079/120] Use qualname for enum repr --- src/object/enum.cpp | 14 ++++++++++++-- test/nested.cpp | 10 ++++++++++ test/nested.py | 9 +++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 5753b32e07..94df8e4aea 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -49,7 +49,9 @@ extern "C" if (!self->name) { return -#if PY_VERSION_HEX >= 0x03000000 +#if PY_VERSION_HEX >= 0x03030000 + PyUnicode_FromFormat("%S.%S(%ld)", mod, ((PyHeapTypeObject*)(self_->ob_type))->ht_qualname, PyLong_AsLong(self_)); +#elif PY_VERSION_HEX >= 0x03000000 PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_)); #else PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_)); @@ -62,7 +64,9 @@ extern "C" return 0; return -#if PY_VERSION_HEX >= 0x03000000 +#if PY_VERSION_HEX >= 0x03030000 + PyUnicode_FromFormat("%S.%S.%S", mod, ((PyHeapTypeObject*)(self_->ob_type))->ht_qualname, name); +#elif PY_VERSION_HEX >= 0x03000000 PyUnicode_FromFormat("%S.%s.%S", mod, self_->ob_type->tp_name, name); #else PyString_FromFormat("%s.%s.%s", @@ -145,6 +149,7 @@ static PyTypeObject enum_type_object = { }; object module_prefix(); +object qualname(const char *name); namespace { @@ -175,6 +180,11 @@ namespace object module_name = module_prefix(); if (module_name) d["__module__"] = module_name; +#if PY_VERSION_HEX >= 0x03030000 + object q = qualname(name); + if (q) + d["__qualname__"] = q; +#endif if (doc) d["__doc__"] = doc; diff --git a/test/nested.cpp b/test/nested.cpp index b807c8bdb9..3a0d05e5ea 100644 --- a/test/nested.cpp +++ b/test/nested.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include "test_class.hpp" @@ -17,6 +18,8 @@ typedef test_class<> X; typedef test_class<1> Y; +enum color { red = 0, blue = 1, green = 2 }; + std::ostream& operator<<(std::ostream& s, X const& x) { return s << x.value(); @@ -45,6 +48,13 @@ BOOST_PYTHON_MODULE(nested_ext) class_("Y", init()) .def(str(self)) ; + + // so will the enum `color` + enum_("color") + .value("red", red) + .value("green", green) + .value("blue", blue) + ; } // The generated docstring will use the fully-qualified name of Y diff --git a/test/nested.py b/test/nested.py index 3d97208b77..f53e7af509 100644 --- a/test/nested.py +++ b/test/nested.py @@ -22,6 +22,15 @@ >>> X.Y.__name__ 'Y' + >>> X.color.__qualname__ + 'X.color' + + >>> repr(X.color.red) + 'nested_ext.X.color.red' + + >>> repr(X.color(1)) + 'nested_ext.X.color(1)' + >>> test_function.__doc__.strip().split('\\n')[0] 'test_function( (X)arg1, (X.Y)arg2) -> None :' From d1910f3d6567a33b7d55d5421297988cf82c6e4d Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Wed, 26 Apr 2023 21:03:32 +0200 Subject: [PATCH 080/120] Avoid degrading slice to object in generated sig --- src/slice.cpp | 10 ++++++++++ test/slice.py | 2 ++ 2 files changed, 12 insertions(+) diff --git a/src/slice.cpp b/src/slice.cpp index ee55f94846..5ff56185de 100644 --- a/src/slice.cpp +++ b/src/slice.cpp @@ -34,4 +34,14 @@ slice_base::step() const ((PySliceObject*)this->ptr())->step)); } +static struct register_slice_pytype_ptr +{ + register_slice_pytype_ptr() + { + const_cast( + converter::registry::lookup(boost::python::type_id()) + ).m_class_object = &PySlice_Type; + } +}register_slice_pytype_ptr_; + } } } // !namespace boost::python::detail diff --git a/test/slice.py b/test/slice.py index c58bbc0299..041934cf57 100644 --- a/test/slice.py +++ b/test/slice.py @@ -33,6 +33,8 @@ 0 >>> check_slice_get_indices( slice( -2, -5, -2)) 6 +>>> check_slice_get_indices.__doc__.strip().split('\\n')[0] +'check_slice_get_indices( (slice)arg1) -> int :' """ # Performs an affirmative and negative argument resolution check. From 4c6f40fb8223e1996385ed6a74d56d96b79b4205 Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Thu, 27 Apr 2023 09:52:03 +0200 Subject: [PATCH 081/120] Add generated docstrings to property fget/fset --- include/boost/python/class.hpp | 10 ++-- .../boost/python/object/add_to_namespace.hpp | 2 + include/boost/python/object/function.hpp | 2 + src/object/function.cpp | 48 ++++++++++++------- test/properties.cpp | 1 + test/properties.py | 22 +++++++++ 6 files changed, 63 insertions(+), 22 deletions(-) diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 77f915ba0a..0f1c0fdc1a 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -372,10 +372,11 @@ class class_ : public objects::class_base { typedef typename api::is_object_operators::type is_obj_or_proxy; - return this->make_fn_impl( + return objects::add_doc( + this->make_fn_impl( detail::unwrap_wrapper((W*)0) , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer() - ); + ), NULL); } template @@ -383,10 +384,11 @@ class class_ : public objects::class_base { typedef typename api::is_object_operators::type is_obj_or_proxy; - return this->make_fn_impl( + return objects::add_doc( + this->make_fn_impl( detail::unwrap_wrapper((W*)0) , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer() - ); + ), NULL); } template diff --git a/include/boost/python/object/add_to_namespace.hpp b/include/boost/python/object/add_to_namespace.hpp index 9f4167d6d2..e81186790a 100644 --- a/include/boost/python/object/add_to_namespace.hpp +++ b/include/boost/python/object/add_to_namespace.hpp @@ -18,6 +18,8 @@ BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL void add_to_namespace( object const& name_space, char const* name, object const& attribute, char const* doc); +BOOST_PYTHON_DECL object const& add_doc(object const& attribute, char const* doc); + }}} // namespace boost::python::objects #endif // ADD_TO_NAMESPACE_DWA200286_HPP diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index b1a1676b63..ec1fc3d38b 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -35,6 +35,8 @@ struct BOOST_PYTHON_DECL function : PyObject static void add_to_namespace( object const& name_space, char const* name, object const& attribute, char const* doc); + static object const& add_doc(object const& attribute, char const* doc); + object const& doc() const; void doc(object const& x); diff --git a/src/object/function.cpp b/src/object/function.cpp index a220befd5b..ec787cf153 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -419,6 +419,30 @@ namespace detail extern char cpp_signature_tag[]; } +object const& function::add_doc(object const& attribute, char const* doc) +{ + str _doc; + + if (docstring_options::show_py_signatures_) + { + _doc += str(const_cast(detail::py_signature_tag)); + } + if (doc != 0 && docstring_options::show_user_defined_) + _doc += doc; + + if (docstring_options::show_cpp_signatures_) + { + _doc += str(const_cast(detail::cpp_signature_tag)); + } + if(_doc) + { + object mutable_attribute(attribute); + mutable_attribute.attr("__doc__")= _doc; + } + + return attribute; +} + void function::add_to_namespace( object const& name_space, char const* name_, object const& attribute, char const* doc) { @@ -545,24 +569,7 @@ void function::add_to_namespace( "C++ signature:", f->signature(true))); } */ - str _doc; - - if (docstring_options::show_py_signatures_) - { - _doc += str(const_cast(detail::py_signature_tag)); - } - if (doc != 0 && docstring_options::show_user_defined_) - _doc += doc; - - if (docstring_options::show_cpp_signatures_) - { - _doc += str(const_cast(detail::cpp_signature_tag)); - } - if(_doc) - { - object mutable_attribute(attribute); - mutable_attribute.attr("__doc__")= _doc; - } + add_doc(attribute, doc); } BOOST_PYTHON_DECL void add_to_namespace( @@ -577,6 +584,11 @@ BOOST_PYTHON_DECL void add_to_namespace( function::add_to_namespace(name_space, name, attribute, doc); } +BOOST_PYTHON_DECL object const& add_doc(object const& attribute, char const* doc) +{ + return function::add_doc(attribute, doc); +} + namespace { diff --git a/test/properties.cpp b/test/properties.cpp index d338beb915..aa1b0a05cf 100644 --- a/test/properties.cpp +++ b/test/properties.cpp @@ -64,6 +64,7 @@ BOOST_PYTHON_MODULE(properties_ext) class_("X", init() ) //defining read only property .add_property( "value_r", &X::get_value ) + .add_property( "value_r_f", make_function(&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 ) diff --git a/test/properties.py b/test/properties.py index 1bc7a624ba..88374b4107 100644 --- a/test/properties.py +++ b/test/properties.py @@ -20,6 +20,9 @@ >>> x1.value_r 1 +>>> x1.value_r_f +1 + value read - write >>> x1.value_rw 1 @@ -84,8 +87,27 @@ class instance count from object: >>> assert properties.X.value_rw_ds.__doc__ == "value_rw_ds is read-write" +>>> properties.X.value_r_f.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' + +>>> properties.X.value_rw_ds.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' + +>>> properties.X.value_rw_ds.fset.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1, (int)arg2) -> None :' + +>>> properties.X.value_rw_ds.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' + +>>> properties.X.value_direct.fset.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1, (int)arg2) -> None :' + +>>> properties.X.value_direct.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' """ +# FIXME: cases to cover: pointer-to-member, preconstructed function + #import sys; sys.path.append(r'P:\Actimize4.0\smart_const\py_smart_const___Win32_Debug') import properties_ext as properties From 0102b319454feffaaad205c7eb028cc6da8210bf Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Tue, 9 May 2023 11:37:27 +0200 Subject: [PATCH 082/120] Unwrap back_reference in get_pytype() This prevents back_reference parameters from decaying to "object" in py signatures --- include/boost/python/converter/pytype_function.hpp | 8 +++++++- test/map_indexing_suite.py | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/include/boost/python/converter/pytype_function.hpp b/include/boost/python/converter/pytype_function.hpp index 8e0a4e7995..d072b55fb3 100644 --- a/include/boost/python/converter/pytype_function.hpp +++ b/include/boost/python/converter/pytype_function.hpp @@ -9,7 +9,7 @@ # include # include # include - +# include namespace boost { namespace python { @@ -46,6 +46,12 @@ inline python::type_info unwind_type_id_(boost::type* = 0, mpl::false_ * =0) return boost::python::detail::unwind_type (); } +template +inline python::type_info unwind_type_id_(boost::type >* = 0, mpl::false_ * =0) +{ + return boost::python::detail::unwind_type (); +} + inline python::type_info unwind_type_id_(boost::type* = 0, mpl::true_* =0) { return type_id(); diff --git a/test/map_indexing_suite.py b/test/map_indexing_suite.py index e772bb53f9..6d3e57a102 100644 --- a/test/map_indexing_suite.py +++ b/test/map_indexing_suite.py @@ -214,6 +214,13 @@ ... i.data() 4 +##################################################################### +# Test signature... +##################################################################### + +>>> AMap.__iter__.__doc__.strip().split("\\n")[0] +'__iter__( (AMap)arg1) -> __main__.iterator :' + ##################################################################### # END.... ##################################################################### From c76d67ef3fe81eb4177cfcaa2d6486395e3aed75 Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Mon, 11 Mar 2024 12:00:14 +0100 Subject: [PATCH 083/120] Ensure that virtual default implementation has the same kwargs as dispatcher --- include/boost/python/pure_virtual.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/python/pure_virtual.hpp b/include/boost/python/pure_virtual.hpp index 58e9aedef1..f3b298de2c 100644 --- a/include/boost/python/pure_virtual.hpp +++ b/include/boost/python/pure_virtual.hpp @@ -96,6 +96,7 @@ namespace detail , make_function( detail::nullary_function_adaptor(pure_virtual_called) , default_call_policies() + , options.keywords() , detail::error_signature(detail::get_signature(m_pmf)) ) ); From 301256cf1e3a626694a991d9548dab66daafc5e3 Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Wed, 18 Sep 2024 11:48:43 +0200 Subject: [PATCH 084/120] Avoid setting __doc__ on instance methods --- src/object/function.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/object/function.cpp b/src/object/function.cpp index ec787cf153..7b6ab9f08b 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -586,6 +586,13 @@ BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL object const& add_doc(object const& attribute, char const* doc) { +#if PY_VERSION_HEX >= 0x03000000 + if (PyInstanceMethod_Check(attribute.ptr())) { +#else + if (PyMethod_Check(attribute.ptr())) { +#endif + return attribute; + } return function::add_doc(attribute, doc); } From 95e53011d816d00d690d91392d81122808fce62c Mon Sep 17 00:00:00 2001 From: Jakob van Santen Date: Wed, 18 Sep 2024 15:13:43 +0200 Subject: [PATCH 085/120] Conditionalize nested test for py2 __qualname__ didn't exist before python 3.3. Skip checks that depend on it if running in earlier Python versions --- test/nested.py | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/test/nested.py b/test/nested.py index f53e7af509..657d100a71 100644 --- a/test/nested.py +++ b/test/nested.py @@ -13,7 +13,10 @@ >>> X.__name__ 'X' - >>> X.Y + >>> X.Y # doctest: +py2 + + + >>> X.Y # doctest: +py3 >>> X.Y.__module__ @@ -22,16 +25,22 @@ >>> X.Y.__name__ 'Y' - >>> X.color.__qualname__ + >>> getattr(X.color, "__qualname__", None) # doctest: +py3 'X.color' - >>> repr(X.color.red) + >>> repr(X.color.red) # doctest: +py2 + 'nested_ext.color.red' + + >>> repr(X.color.red) # doctest: +py3 'nested_ext.X.color.red' - >>> repr(X.color(1)) + >>> repr(X.color(1)) # doctest: +py2 + 'nested_ext.color(1)' + + >>> repr(X.color(1)) # doctest: +py3 'nested_ext.X.color(1)' - >>> test_function.__doc__.strip().split('\\n')[0] + >>> test_function.__doc__.strip().split('\\n')[0] # doctest: +py3 'test_function( (X)arg1, (X.Y)arg2) -> None :' ''' @@ -42,7 +51,23 @@ def run(args = None): if args is not None: sys.argv = args - return doctest.testmod(sys.modules.get(__name__)) + + py2 = doctest.register_optionflag("py2") + py3 = doctest.register_optionflag("py3") + + class ConditionalChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if (optionflags & py3) and (sys.version_info[0] < 3): + return True + if (optionflags & py2) and (sys.version_info[0] >= 3): + return True + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + runner = doctest.DocTestRunner(ConditionalChecker()) + for test in doctest.DocTestFinder().find(sys.modules.get(__name__)): + runner.run(test) + + return doctest.TestResults(runner.failures, runner.tries) if __name__ == '__main__': print("running...") From 3ea0cb8501dd64223e32e6db376b259f7fade14b Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 17 Sep 2024 21:06:48 -0400 Subject: [PATCH 086/120] Upgrade CI platforms. --- .github/workflows/test-osx.yml | 11 +++++++---- .github/workflows/test-ubuntu.yml | 2 +- .github/workflows/test-windows.yml | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml index 19928d875b..03b99f8ca7 100644 --- a/.github/workflows/test-osx.yml +++ b/.github/workflows/test-osx.yml @@ -9,14 +9,14 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.6] + python-version: [3.8.10] cxx: [clang++] - std: [c++98, c++11, c++14] # TODO: c++17 is failing ! + std: [c++11, c++14] # TODO: c++17 is failing ! steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: setup python - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: setup prerequisites @@ -28,9 +28,11 @@ jobs: run: | python --version ${{ matrix.cxx }} --version + brew info boost faber -v sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber faber \ + --with-boost-include=/opt/homebrew/Cellar/boost/1.86.0/include \ --builddir=build \ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ @@ -38,6 +40,7 @@ jobs: - name: test run: | faber \ + --with-boost-include=/opt/homebrew/Cellar/boost/1.86.0/include \ --builddir=build\ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index dab98aee4a..9910232e82 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -26,7 +26,7 @@ jobs: image: ${{ matrix.docker-img }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: build run: | diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 36c4a8e4f0..e7b02927b2 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -11,8 +11,8 @@ jobs: python-version: [3.7] steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - uses: microsoft/setup-msbuild@v1.1 From b3a28d70339a3da41fb5f0beb54840268a290f70 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 17 Sep 2024 20:40:19 -0400 Subject: [PATCH 087/120] Use the expected return type. --- src/object/class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index 5b5095151d..1a198408a3 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -502,7 +502,7 @@ namespace objects ); } - str qualname(const char *name) + object qualname(const char *name) { #if PY_VERSION_HEX >= 0x03030000 if (PyObject_HasAttrString(scope().ptr(), "__qualname__")) { From b988d702074b3227967f3d440865d0659583f255 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20La=C3=BCgt?= Date: Mon, 29 Aug 2022 10:37:00 +0200 Subject: [PATCH 088/120] Alignment fixes --- include/boost/python/make_constructor.hpp | 3 ++- src/object/class.cpp | 7 +++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/boost/python/make_constructor.hpp b/include/boost/python/make_constructor.hpp index 3ec9ad5f86..3769970cad 100644 --- a/include/boost/python/make_constructor.hpp +++ b/include/boost/python/make_constructor.hpp @@ -61,7 +61,8 @@ namespace detail typedef objects::pointer_holder holder; typedef objects::instance instance_t; - void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder)); + void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder), + boost::python::detail::alignment_of::value); try { #if defined(BOOST_NO_CXX11_SMART_PTR) (new (memory) holder(x))->install(this->m_self); diff --git a/src/object/class.cpp b/src/object/class.cpp index 1a198408a3..8bb462cee2 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -766,10 +766,9 @@ void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std: throw std::bad_alloc(); const uintptr_t x = reinterpret_cast(base_storage) + sizeof(alignment_marker_t); - //this has problems for x -> max(void *) - //const size_t padding = alignment - ((x + sizeof(alignment_marker_t)) % alignment); - //only works for alignments with alignments of powers of 2, but no edge conditions - const uintptr_t padding = alignment == 1 ? 0 : ( alignment - (x & (alignment - 1)) ); + // Padding required to align the start of a data structure is: (alignment - (x % alignment)) % alignment + // Since the alignment is a power of two, the formula can be simplified with bitwise AND operator as follow: + const uintptr_t padding = (alignment - (x & (alignment - 1))) & (alignment - 1); const size_t aligned_offset = sizeof(alignment_marker_t) + padding; void* const aligned_storage = (char *)base_storage + aligned_offset; BOOST_ASSERT((char *) aligned_storage + holder_size <= (char *)base_storage + base_allocation); From ff0ae9b29d7707d63d6f0ad4a64b578021783693 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Fri, 3 Jun 2022 20:49:17 -0700 Subject: [PATCH 089/120] dynamic_cast before destructor Call to the destructor ends lifetime of the object, including vptr used by dynamic_cast. --- src/object/class.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/object/class.cpp b/src/object/class.cpp index 8bb462cee2..e03d4e009a 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -333,8 +333,9 @@ namespace objects for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) { next = p->next(); + void* q = dynamic_cast(p); p->~instance_holder(); - instance_holder::deallocate(inst, dynamic_cast(p)); + instance_holder::deallocate(inst, q); } // Python 2.2.1 won't add weak references automatically when From 4fc3afa3ac1a1edb61a92fccd31d305ba38213f8 Mon Sep 17 00:00:00 2001 From: sdarwin Date: Wed, 5 Oct 2022 20:56:23 +0000 Subject: [PATCH 090/120] Support newer version of Sphinx --- doc/numpy/_static/boost.css | 20 ++++++++++++++++++++ doc/numpy/_templates/layout.html | 3 +++ 2 files changed, 23 insertions(+) diff --git a/doc/numpy/_static/boost.css b/doc/numpy/_static/boost.css index 28f8935991..36c1efd082 100644 --- a/doc/numpy/_static/boost.css +++ b/doc/numpy/_static/boost.css @@ -714,3 +714,23 @@ span.purple { color: purple; } span.gold { color: gold; } span.silver { color: silver; } /* lighter gray */ span.gray { color: #808080; } /* light gray */ + +/* 2022 fix */ + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + diff --git a/doc/numpy/_templates/layout.html b/doc/numpy/_templates/layout.html index 1aa68f0ea1..d85f075141 100644 --- a/doc/numpy/_templates/layout.html +++ b/doc/numpy/_templates/layout.html @@ -49,6 +49,9 @@ {%- for scriptfile in script_files %} {%- endfor %} + + + {%- if use_opensearch %} Date: Tue, 28 Jan 2025 02:27:49 +0200 Subject: [PATCH 091/120] Replace use of boost/iterator/detail/enable_if.hpp --- include/boost/python/object_operators.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/boost/python/object_operators.hpp b/include/boost/python/object_operators.hpp index d436bb0144..45d6d028cc 100644 --- a/include/boost/python/object_operators.hpp +++ b/include/boost/python/object_operators.hpp @@ -9,7 +9,7 @@ # include # include -# include +# include # include # include @@ -40,7 +40,7 @@ struct is_object_operators # if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) template struct enable_binary - : boost::iterators::enable_if, T> + : boost::enable_if_::value, T> {}; # define BOOST_PYTHON_BINARY_RETURN(T) typename enable_binary::type # else From b1b43f1e1a535827640833c5214755c28348da5e Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 1 Feb 2025 13:29:06 -0500 Subject: [PATCH 092/120] Fix homebrew include path. --- .github/workflows/test-osx.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml index 03b99f8ca7..bf2008d4d6 100644 --- a/.github/workflows/test-osx.yml +++ b/.github/workflows/test-osx.yml @@ -32,7 +32,7 @@ jobs: faber -v sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber faber \ - --with-boost-include=/opt/homebrew/Cellar/boost/1.86.0/include \ + --with-boost-include=$(brew --prefix boost)/include \ --builddir=build \ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ @@ -40,7 +40,7 @@ jobs: - name: test run: | faber \ - --with-boost-include=/opt/homebrew/Cellar/boost/1.86.0/include \ + --with-boost-include=$(brew --prefix boost)/include \ --builddir=build\ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ From 4fe3403584a8d029d316abd0af6037ec70c36d9e Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 1 Feb 2025 22:15:24 -0500 Subject: [PATCH 093/120] Make sure to pass C++ version to preprocessor as well. --- .github/workflows/test-osx.yml | 2 ++ .github/workflows/test-ubuntu.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml index bf2008d4d6..2521c09a9b 100644 --- a/.github/workflows/test-osx.yml +++ b/.github/workflows/test-osx.yml @@ -36,6 +36,7 @@ jobs: --builddir=build \ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ -j`sysctl -n hw.ncpu` - name: test run: | @@ -44,5 +45,6 @@ jobs: --builddir=build\ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ -j`sysctl -n hw.ncpu` \ test.report diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 9910232e82..74718b68a5 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -39,6 +39,7 @@ jobs: --builddir=build \ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ -j`nproc` - name: test run: | @@ -47,5 +48,6 @@ jobs: --builddir=build \ cxx.name=${{ matrix.cxx }} \ cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ -j`nproc` \ test.report From cbdf1ce2a1f68abbc64729e9026e312fb858e3c6 Mon Sep 17 00:00:00 2001 From: Aditya Pillai Date: Mon, 10 Mar 2025 14:03:41 -0400 Subject: [PATCH 094/120] Use Py_REFCNT instead of ->ob_refcnt Py_REFCNT was stabilized in 3.9, uses this official API instead of the `ob_refcnt` field that doesn't exist in the free-threaded build of 3.13. --- src/converter/from_python.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 9678be1cb6..589d99effe 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -222,7 +222,7 @@ namespace , char const* ref_type) { handle<> holder(source); - if (source->ob_refcnt <= 1) + if (Py_REFCNT(source) <= 1) { handle<> msg( #if PY_VERSION_HEX >= 0x3000000 From 3e7be69e1e405e1d5ddd232c69c024ee441592c5 Mon Sep 17 00:00:00 2001 From: Aditya Pillai Date: Mon, 10 Mar 2025 14:19:34 -0400 Subject: [PATCH 095/120] Conditionally use Py_REFCNT --- src/converter/from_python.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 589d99effe..f3989ba77f 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -222,7 +222,13 @@ namespace , char const* ref_type) { handle<> holder(source); - if (Py_REFCNT(source) <= 1) + if ( +#if PY_VERSION_HEX < 0x03090000 + source->ob_refcnt +#else + Py_REFCNT(source) +#endif + <= 1) { handle<> msg( #if PY_VERSION_HEX >= 0x3000000 From d30c1bb7a8a6d424b06b62cc692cfbf78add397b Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Fri, 28 Mar 2025 07:52:16 +0900 Subject: [PATCH 096/120] refactor: switch to python 3 --- doc/numpy/conf.py | 12 ++++++------ example/numpy/demo_gaussian.py | 13 +++++++------ example/quickstart/script.py | 2 +- example/quickstart/test_extending.py | 2 +- example/tutorial/hello.py | 2 +- test/numpy/dtype.py | 4 ++-- test/numpy/indexing.py | 2 +- test/numpy/ndarray.py | 10 +++++----- test/numpy/shapes.py | 2 +- test/numpy/templates.py | 4 ++-- test/numpy/ufunc.py | 6 +++--- test/test_cltree.py | 2 +- 12 files changed, 31 insertions(+), 30 deletions(-) diff --git a/doc/numpy/conf.py b/doc/numpy/conf.py index 2f5d5e8146..23ab678d3a 100644 --- a/doc/numpy/conf.py +++ b/doc/numpy/conf.py @@ -40,8 +40,8 @@ master_doc = 'index' # General information about the project. -project = u'Boost.Python NumPy extension' -copyright = u'2011, Stefan Seefeld' +project = 'Boost.Python NumPy extension' +copyright = '2011, Stefan Seefeld' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -181,8 +181,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'BoostPythonNumPy.tex', u'Boost.Python NumPy Documentation', - u'Stefan Seefeld', 'manual'), + ('index', 'BoostPythonNumPy.tex', 'Boost.Python NumPy Documentation', + 'Stefan Seefeld', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -214,6 +214,6 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'boostnumpy', u'Boost.Python NumPy Documentation', - [u'Stefan Seefeld'], 1) + ('index', 'boostnumpy', 'Boost.Python NumPy Documentation', + ['Stefan Seefeld'], 1) ] diff --git a/example/numpy/demo_gaussian.py b/example/numpy/demo_gaussian.py index 0b1c78995e..08bb58b82a 100644 --- a/example/numpy/demo_gaussian.py +++ b/example/numpy/demo_gaussian.py @@ -3,6 +3,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +from __future__ import print_function import numpy import gaussian @@ -19,19 +20,19 @@ z = g(x, y) s = z.sum() * (r[1] - r[0])**2 -print "sum (should be ~ 1):", s +print("sum (should be ~ 1):", s) xc = (z * x).sum() / z.sum() -print "x centroid (should be ~ %f): %f" % (mu[0], xc) +print("x centroid (should be ~ %f): %f" % (mu[0], xc)) yc = (z * y).sum() / z.sum() -print "y centroid (should be ~ %f): %f" % (mu[1], yc) +print("y centroid (should be ~ %f): %f" % (mu[1], yc)) xx = (z * (x - xc)**2).sum() / z.sum() -print "xx moment (should be ~ %f): %f" % (sigma[0,0], xx) +print("xx moment (should be ~ %f): %f" % (sigma[0,0], xx)) yy = (z * (y - yc)**2).sum() / z.sum() -print "yy moment (should be ~ %f): %f" % (sigma[1,1], yy) +print("yy moment (should be ~ %f): %f" % (sigma[1,1], yy)) xy = 0.5 * (z * (x - xc) * (y - yc)).sum() / z.sum() -print "xy moment (should be ~ %f): %f" % (sigma[0,1], xy) +print("xy moment (should be ~ %f): %f" % (sigma[0,1], xy)) diff --git a/example/quickstart/script.py b/example/quickstart/script.py index c3e034ba84..f360cef2d2 100644 --- a/example/quickstart/script.py +++ b/example/quickstart/script.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # 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) diff --git a/example/quickstart/test_extending.py b/example/quickstart/test_extending.py index 938c7b9047..035ca96134 100644 --- a/example/quickstart/test_extending.py +++ b/example/quickstart/test_extending.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # Copyright Ralf W. Grosse-Kunstleve 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) diff --git a/example/tutorial/hello.py b/example/tutorial/hello.py index 31f75565df..7888b2e0fd 100755 --- a/example/tutorial/hello.py +++ b/example/tutorial/hello.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # Copyright Joel de Guzman 2002-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) diff --git a/test/numpy/dtype.py b/test/numpy/dtype.py index a27ee0f55d..a2eabb58e2 100644 --- a/test/numpy/dtype.py +++ b/test/numpy/dtype.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -15,7 +15,7 @@ class DtypeTestCase(unittest.TestCase): def assertEquivalent(self, a, b): - return self.assert_(dtype_ext.equivalent(a, b), "%r is not equivalent to %r") + return self.assertTrue(dtype_ext.equivalent(a, b), "%r is not equivalent to %r") def testIntegers(self): for bits in (8, 16, 32, 64): diff --git a/test/numpy/indexing.py b/test/numpy/indexing.py index ebd9dcbabb..3fb9adb4c0 100644 --- a/test/numpy/indexing.py +++ b/test/numpy/indexing.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. diff --git a/test/numpy/ndarray.py b/test/numpy/ndarray.py index 2acc384a52..13f3c73e42 100644 --- a/test/numpy/ndarray.py +++ b/test/numpy/ndarray.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -19,7 +19,7 @@ def testNdzeros(self): a1 = ndarray_ext.zeros(shape,dt) a2 = v.reshape(a1.shape) self.assertEqual(shape,a1.shape) - self.assert_((a1 == a2).all()) + self.assertTrue((a1 == a2).all()) def testNdzeros_matrix(self): for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): @@ -28,7 +28,7 @@ def testNdzeros_matrix(self): 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.assertTrue((a1 == a2).all()) self.assertEqual(type(a1), type(a2)) def testNdarray(self): @@ -38,8 +38,8 @@ def testNdarray(self): 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()) + self.assertTrue((a1 == v).all()) + self.assertTrue((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) diff --git a/test/numpy/shapes.py b/test/numpy/shapes.py index d0a0099ca6..28c74b7b18 100644 --- a/test/numpy/shapes.py +++ b/test/numpy/shapes.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. diff --git a/test/numpy/templates.py b/test/numpy/templates.py index 8290b13a07..9c21622881 100755 --- a/test/numpy/templates.py +++ b/test/numpy/templates.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -18,7 +18,7 @@ def testTemplates(self): a1 = numpy.zeros(shape, dtype=dtype) a2 = v.reshape(a1.shape) templates_ext.fill(a1) - self.assert_((a1 == a2).all()) + self.assertTrue((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) diff --git a/test/numpy/ufunc.py b/test/numpy/ufunc.py index e820121ee1..380cc5683e 100755 --- a/test/numpy/ufunc.py +++ b/test/numpy/ufunc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -24,7 +24,7 @@ def testArray(self): assert_array_almost_equal(b, a*2.0) c = numpy.zeros(5, dtype=float) d = f(a,output=c) - self.assert_(c is d) + self.assertTrue(c is d) assert_array_almost_equal(d, a*2.0) def testList(self): @@ -47,7 +47,7 @@ def testArray(self): 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) + self.assertTrue(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) diff --git a/test/test_cltree.py b/test/test_cltree.py index 2127b7cdb6..d5df6fc5a0 100644 --- a/test/test_cltree.py +++ b/test/test_cltree.py @@ -1,7 +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) -#!/usr/bin/env python +#!/usr/bin/env python3 from cltree import basic,symbol,constant,variable From f604eb8d0f99f5c16831cd4ccd86d9edc859c189 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Mon, 31 Mar 2025 23:33:50 +0900 Subject: [PATCH 097/120] fix(test.numpy/ufunc): fix import error and value comparison --- test/numpy/ufunc.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/numpy/ufunc.py b/test/numpy/ufunc.py index 380cc5683e..1fa3090b3e 100755 --- a/test/numpy/ufunc.py +++ b/test/numpy/ufunc.py @@ -8,7 +8,10 @@ import ufunc_ext import unittest import numpy -from numpy.testing.utils import assert_array_almost_equal +try: + from numpy.testing import assert_array_almost_equal +except ImportError: + from numpy.testing.utils import assert_array_almost_equal class TestUnary(unittest.TestCase): @@ -24,7 +27,7 @@ def testArray(self): assert_array_almost_equal(b, a*2.0) c = numpy.zeros(5, dtype=float) d = f(a,output=c) - self.assertTrue(c is d) + self.assertTrue((c == d).all()) assert_array_almost_equal(d, a*2.0) def testList(self): @@ -47,7 +50,7 @@ def testArray(self): assert_array_almost_equal(f(a,b), (a*2+b*3)) c = numpy.zeros(5, dtype=float) d = f(a,b,output=c) - self.assertTrue(c is d) + self.assertTrue((c == d).all()) 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) From a40bb656ee0f26f470444a47ea26701a4baca2e5 Mon Sep 17 00:00:00 2001 From: Aditya Pillai Date: Mon, 12 May 2025 15:09:01 -0400 Subject: [PATCH 098/120] Use Py_REFCNT instead of ob_refcnt on Python 3.9 and above --- .../suite/indexing/detail/indexing_suite_detail.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp b/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp index eb8b81c0a3..d470e32d77 100644 --- a/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp +++ b/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp @@ -216,7 +216,13 @@ namespace boost { namespace python { namespace detail { { for (const_iterator i = proxies.begin(); i != proxies.end(); ++i) { - if ((*i)->ob_refcnt <= 0) + if ( +#if PY_VERSION_HEX < 0x03090000 + (*i)->ob_refcnt +#else + Py_REFCNT(*i) +#endif + <= 0) { PyErr_SetString(PyExc_RuntimeError, "Invariant: Proxy vector in an inconsistent state"); From 867f0dddfe89f066420382dc250d4406f720850e Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Thu, 23 Oct 2025 20:25:07 -0400 Subject: [PATCH 099/120] Fix windows header path. --- .github/workflows/test-windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index e7b02927b2..cc3d982484 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -42,8 +42,8 @@ jobs: - name: build shell: cmd run: | - faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}/vcpkg/installed/x64-windows/include -j4 + faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}\vcpkg\installed\x64-windows\include -j4 - name: test shell: cmd run: | - faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}/vcpkg/installed/x64-windows/include -j4 test.report + faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}\vcpkg\installed\x64-windows\include -j4 test.report From b4fb28e99a1ba5ed23d597d38e70e72e261a03eb Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Fri, 24 Oct 2025 06:40:33 +0900 Subject: [PATCH 100/120] ci: update GitHub Actions --- .github/workflows/deploy-documentation.yml | 8 ++++---- .github/workflows/test-osx.yml | 4 ++-- .github/workflows/test-ubuntu.yml | 2 +- .github/workflows/test-windows.yml | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy-documentation.yml b/.github/workflows/deploy-documentation.yml index 065945137b..3c5ffafb70 100644 --- a/.github/workflows/deploy-documentation.yml +++ b/.github/workflows/deploy-documentation.yml @@ -4,14 +4,14 @@ on: [push] jobs: deploy: - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - name: setup run: | sudo apt-get update sudo apt-get install \ - libboost1.71-tools-dev \ + libboost-tools-dev \ python3 \ python3-numpy \ python3-sphinx \ @@ -29,7 +29,7 @@ jobs: echo "destination_dir=doc/develop/html" >> $GITHUB_ENV fi - name: deploy - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: build/doc/html diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml index 2521c09a9b..b88b43e5dd 100644 --- a/.github/workflows/test-osx.yml +++ b/.github/workflows/test-osx.yml @@ -14,9 +14,9 @@ jobs: std: [c++11, c++14] # TODO: c++17 is failing ! steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: setup python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: setup prerequisites diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 74718b68a5..41185c0dc0 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -26,7 +26,7 @@ jobs: image: ${{ matrix.docker-img }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: build run: | diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index cc3d982484..b11f14b453 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -11,13 +11,13 @@ jobs: python-version: [3.7] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - - uses: microsoft/setup-msbuild@v1.1 + - uses: microsoft/setup-msbuild@v2 - name: setup boost prerequisites - uses: lukka/run-vcpkg@v6 + uses: lukka/run-vcpkg@v11 with: vcpkgGitCommitId: '88b1071e39f13b632644d9d953738d345a4ac055' vcpkgDirectory: '${{ runner.workspace }}/vcpkg' From cb95b611bbf708f9c92a3fe97a95b848dadb578f Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Fri, 24 Oct 2025 08:45:04 -0400 Subject: [PATCH 101/120] Downgrade run-vcpkg dependency to avoid regression. --- .github/workflows/test-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index b11f14b453..f9edc3ee86 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -17,7 +17,7 @@ jobs: python-version: ${{ matrix.python-version }} - uses: microsoft/setup-msbuild@v2 - name: setup boost prerequisites - uses: lukka/run-vcpkg@v11 + uses: lukka/run-vcpkg@v6 with: vcpkgGitCommitId: '88b1071e39f13b632644d9d953738d345a4ac055' vcpkgDirectory: '${{ runner.workspace }}/vcpkg' From 303299e6775aed26e9f6b29d5e4d382c558eb97e Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Fri, 24 Oct 2025 09:41:39 -0400 Subject: [PATCH 102/120] log commands --- .github/workflows/test-windows.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index f9edc3ee86..576e1f4415 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -42,7 +42,7 @@ jobs: - name: build shell: cmd run: | - faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}\vcpkg\installed\x64-windows\include -j4 + faber --builddir=build cxx.name=msvc --log=commands --log=output --with-boost-include=${{ runner.workspace }}\vcpkg\installed\x64-windows\include -j4 - name: test shell: cmd run: | From 16627261f10b7507a380b5487c25c145f0fb5576 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Mon, 31 Mar 2025 19:49:28 +0900 Subject: [PATCH 103/120] fix(test.pickle): fix for change in the return value of object.__reduce__() https://docs.python.org/3.11/library/pickle.html#object.__reduce__ fix #461 --- test/pickle1.py | 26 ++++++++++++++++++++++++-- test/pickle4.py | 26 ++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/test/pickle1.py b/test/pickle1.py index b8f4efd9b0..0df59a4b3a 100644 --- a/test/pickle1.py +++ b/test/pickle1.py @@ -9,8 +9,10 @@ 1 >>> pickle1_ext.world.__name__ 'world' - >>> pickle1_ext.world('Hello').__reduce__() + >>> pickle1_ext.world('Hello').__reduce__() # doctest: +PY310 (, ('Hello',)) + >>> pickle1_ext.world('Hello').__reduce__() # doctest: +PY311 + (, ('Hello',), None) >>> wd = pickle1_ext.world('California') >>> pstr = pickle.dumps(wd) >>> wl = pickle.loads(pstr) @@ -31,7 +33,27 @@ def run(args = None): if args is not None: sys.argv = args - return doctest.testmod(sys.modules.get(__name__)) + + # > https://docs.python.org/3.11/library/pickle.html#object.__reduce__ + # object.__reduce__() returns + # - python 3.10 or prior: a 2-element tuple + # - python 3.11 or later: a 3-element tuple (object's state added) + PY310 = doctest.register_optionflag("PY310") + PY311 = doctest.register_optionflag("PY311") + + class ConditionalChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if (optionflags & PY311) and (sys.version_info[:2] < (3, 11)): + return True + if (optionflags & PY310) and (sys.version_info[:2] >= (3, 11)): + return True + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + runner = doctest.DocTestRunner(ConditionalChecker()) + for test in doctest.DocTestFinder().find(sys.modules.get(__name__)): + runner.run(test) + + return doctest.TestResults(runner.failures, runner.tries) if __name__ == '__main__': print("running...") diff --git a/test/pickle4.py b/test/pickle4.py index be813bbb13..3cf4d7241f 100644 --- a/test/pickle4.py +++ b/test/pickle4.py @@ -12,8 +12,10 @@ 1 >>> pickle4_ext.world.__name__ 'world' - >>> pickle4_ext.world('Hello').__reduce__() + >>> pickle4_ext.world('Hello').__reduce__() # doctest: +PY310 (, ('Hello',)) + >>> pickle4_ext.world('Hello').__reduce__() # doctest: +PY311 + (, ('Hello',), None) >>> wd = pickle4_ext.world('California') >>> pstr = pickle.dumps(wd) >>> wl = pickle.loads(pstr) @@ -29,7 +31,27 @@ def run(args = None): if args is not None: sys.argv = args - return doctest.testmod(sys.modules.get(__name__)) + + # > https://docs.python.org/3.11/library/pickle.html#object.__reduce__ + # object.__reduce__() returns + # - python 3.10 or prior: a 2-element tuple + # - python 3.11 or later: a 3-element tuple (object's state added) + PY310 = doctest.register_optionflag("PY310") + PY311 = doctest.register_optionflag("PY311") + + class ConditionalChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if (optionflags & PY311) and (sys.version_info[:2] < (3, 11)): + return True + if (optionflags & PY310) and (sys.version_info[:2] >= (3, 11)): + return True + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + runner = doctest.DocTestRunner(ConditionalChecker()) + for test in doctest.DocTestFinder().find(sys.modules.get(__name__)): + runner.run(test) + + return doctest.TestResults(runner.failures, runner.tries) if __name__ == '__main__': print("running...") From aa458d2ca959bc93ff78e0d39eae9eb17e05cbf6 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Mon, 31 Mar 2025 19:54:55 +0900 Subject: [PATCH 104/120] fix(test.properties): use doctest.ELLIPSIS for traceback Since python 3.11 (PEP 657) traceback info is changed fix #460 --- test/properties.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/properties.py b/test/properties.py index 88374b4107..e95d59bef2 100644 --- a/test/properties.py +++ b/test/properties.py @@ -56,11 +56,10 @@ class instance count from object: 1 as expected you can't assign new value to read only property ->>> x1.value_r = 2 +>>> x1.value_r = 2 # doctest: +ELLIPSIS Traceback (most recent call last): - File "properties.py", line 49, in ? - x1.value_r = 2 -AttributeError: can't set attribute + ... +AttributeError: ... setting value_rw to 2. value_direct: >>> x1.value_rw = 2 From 2b6f667e987c81e91e7cf805e15ec19863f83ed3 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Wed, 22 Jan 2025 11:25:51 +0900 Subject: [PATCH 105/120] chore: remove meaningless comparison --- src/object/function.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/object/function.cpp b/src/object/function.cpp index 7b6ab9f08b..fec56768da 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -161,7 +161,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const else { // build a new arg tuple, will adjust its size later - assert(max_arity <= static_cast(ssize_t_max)); inner_args = handle<>( PyTuple_New(static_cast(max_arity))); From 7fd39323acb89378882f6188ca2d3f63de199c08 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sat, 1 Nov 2025 22:30:52 -0400 Subject: [PATCH 106/120] Don't rely on Py_REFCNT to test upcast. --- test/upcast.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/upcast.cpp b/test/upcast.cpp index 255429f168..e005900410 100644 --- a/test/upcast.cpp +++ b/test/upcast.cpp @@ -13,7 +13,7 @@ int main() { PyTypeObject o; Y y; - BOOST_TEST(&Py_REFCNT(boost::python::upcast(&o)) == &Py_REFCNT(&o)); - BOOST_TEST(&Py_REFCNT(boost::python::upcast(&y)) == &Py_REFCNT(&y)); + BOOST_TEST(boost::python::upcast(&o) == reinterpret_cast(&o)); + BOOST_TEST(boost::python::upcast(&y) == &y); return boost::report_errors(); } From 608ec27c4d59800fec21c8d19b381a815f9c8e75 Mon Sep 17 00:00:00 2001 From: Tom Kent Date: Tue, 28 Oct 2025 19:01:46 -0500 Subject: [PATCH 107/120] Updated to recent compilers/boost --- .github/workflows/test-ubuntu.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 41185c0dc0..a85c21ee96 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -18,9 +18,9 @@ jobs: # pre-reqs installed, see: # https://github.com/teeks99/boost-python-test-docker - cxx: clang++ - docker-img: teeks99/boost-python-test:clang-12_1.76.0 + docker-img: teeks99/boost-python-test:clang-21_1.89.0 - cxx: g++ - docker-img: teeks99/boost-python-test:gcc-10_1.76.0 + docker-img: teeks99/boost-python-test:gcc-15_1.89.0 container: image: ${{ matrix.docker-img }} From 5d7b9a064811392d9fe3f19ebbaef9cd32fdbaa7 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 2 Nov 2025 09:33:34 -0500 Subject: [PATCH 108/120] Stop testing c++98 support --- .github/workflows/test-ubuntu.yml | 2 +- fabscript | 1 + include/boost/python/detail/is_auto_ptr.hpp | 2 ++ test/back_reference.cpp | 2 +- test/copy_ctor_mutates_rhs.cpp | 3 +-- test/fabscript | 8 ++++---- test/injected.cpp | 2 +- test/operators_wrapper.cpp | 4 ++-- test/select_holder.cpp | 12 ++++++------ test/wrapper_held_type.cpp | 8 ++++---- 10 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index a85c21ee96..aceeb59334 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -11,7 +11,7 @@ jobs: matrix: python: [python, python3] cxx: [g++, clang++] - std: [c++98, c++11, c++14, c++17] + std: [c++11, c++14, c++17] include: # Add the appropriate docker image for each compiler. # The images from teeks99/boost-python-test already have boost::python diff --git a/fabscript b/fabscript index 8188779fd3..5a50615fc8 100644 --- a/fabscript +++ b/fabscript @@ -16,6 +16,7 @@ from faber.config.try_run import try_run features += include('include') features += define('BOOST_ALL_NO_LIB') # disable auto-linking +features += define('BOOST_NO_AUTO_PTR') boost_include = options.get_with('boost-include') if boost_include: features += include(boost_include) diff --git a/include/boost/python/detail/is_auto_ptr.hpp b/include/boost/python/detail/is_auto_ptr.hpp index 3b8198b8dd..36affcd215 100644 --- a/include/boost/python/detail/is_auto_ptr.hpp +++ b/include/boost/python/detail/is_auto_ptr.hpp @@ -8,6 +8,8 @@ # ifndef BOOST_NO_AUTO_PTR # include # include +# else +# include # endif namespace boost { namespace python { namespace detail { diff --git a/test/back_reference.cpp b/test/back_reference.cpp index 266ed29125..11e47b3321 100644 --- a/test/back_reference.cpp +++ b/test/back_reference.cpp @@ -99,7 +99,7 @@ BOOST_PYTHON_MODULE(back_reference_ext) .def("set", &Y::set) ; - class_ >("Z", init()) + class_ >("Z", init()) .def("value", &Z::value) .def("set", &Z::set) ; diff --git a/test/copy_ctor_mutates_rhs.cpp b/test/copy_ctor_mutates_rhs.cpp index 41eac495e4..be52c4f327 100644 --- a/test/copy_ctor_mutates_rhs.cpp +++ b/test/copy_ctor_mutates_rhs.cpp @@ -9,14 +9,13 @@ struct foo { - operator std::auto_ptr&() const; + operator std::shared_ptr&() const; }; int main() { using namespace boost::python::detail; BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); - BOOST_STATIC_ASSERT(copy_ctor_mutates_rhs >::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); return 0; diff --git a/test/fabscript b/test/fabscript index d4d7ead83b..a002fb2bf0 100644 --- a/test/fabscript +++ b/test/fabscript @@ -118,10 +118,10 @@ for t in [('injected',), 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'))) +#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': diff --git a/test/injected.cpp b/test/injected.cpp index 73e1e14baa..82db3e82e6 100644 --- a/test/injected.cpp +++ b/test/injected.cpp @@ -17,7 +17,7 @@ typedef test_class<> X; X* empty() { return new X(1000); } -std::auto_ptr sum(int a, int b) { return std::auto_ptr(new X(a+b)); } +std::shared_ptr sum(int a, int b) { return std::shared_ptr(new X(a+b)); } boost::shared_ptr product(int a, int b, int c) { diff --git a/test/operators_wrapper.cpp b/test/operators_wrapper.cpp index 12f30048d0..e62ead16f8 100644 --- a/test/operators_wrapper.cpp +++ b/test/operators_wrapper.cpp @@ -36,7 +36,7 @@ BOOST_PYTHON_MODULE( operators_wrapper_ext ) ; scope().attr("v") = vector(); - std::auto_ptr dp(new dvector); - register_ptr_to_python< std::auto_ptr >(); + std::shared_ptr dp(new dvector); + register_ptr_to_python< std::shared_ptr >(); scope().attr("d") = dp; } diff --git a/test/select_holder.cpp b/test/select_holder.cpp index 8650bd06a0..77aac67868 100644 --- a/test/select_holder.cpp +++ b/test/select_holder.cpp @@ -62,14 +62,14 @@ int test_main(int, char * []) assert_holder >(); - assert_holder - ,pointer_holder,Base> >(); + assert_holder + ,pointer_holder,Base> >(); - assert_holder - ,pointer_holder_back_reference,Base> >(); + assert_holder + ,pointer_holder_back_reference,Base> >(); - assert_holder - ,pointer_holder_back_reference,BR> > (); + assert_holder + ,pointer_holder_back_reference,BR> > (); return 0; } diff --git a/test/wrapper_held_type.cpp b/test/wrapper_held_type.cpp index e99422796e..ef494924b9 100644 --- a/test/wrapper_held_type.cpp +++ b/test/wrapper_held_type.cpp @@ -20,12 +20,12 @@ struct data } }; -std::auto_ptr create_data() +std::shared_ptr create_data() { - return std::auto_ptr( new data ); + return std::shared_ptr( new data ); } -void do_nothing( std::auto_ptr& ){} +void do_nothing( std::shared_ptr& ){} namespace bp = boost::python; @@ -59,7 +59,7 @@ struct data_wrapper : data, bp::wrapper< data > BOOST_PYTHON_MODULE(wrapper_held_type_ext) { - bp::class_< data_wrapper, std::auto_ptr< data > >( "data" ) + bp::class_< data_wrapper, std::shared_ptr< data > >( "data" ) .def( "id", &data::id, &::data_wrapper::default_id ); bp::def( "do_nothing", &do_nothing ); From 20de46cd0cf0038fa97574cde6a102433cd9f4f5 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 2 Nov 2025 14:06:12 -0500 Subject: [PATCH 109/120] Update faber --- .github/workflows/test-ubuntu.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index aceeb59334..6f94c2d186 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -28,6 +28,10 @@ jobs: steps: - uses: actions/checkout@v5 + - name: setup prerequisites + run: | + # Warning: this is not necessarily the same Python version as the one configured above ! + python3 -m pip install -U faber --break-system-packages - name: build run: | ${{ matrix.python }} --version From cc873d968278445e3524eabecff8880569154add Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Sun, 2 Nov 2025 15:35:47 -0500 Subject: [PATCH 110/120] Fix documentation build error. --- doc/numpy/_templates/layout.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/numpy/_templates/layout.html b/doc/numpy/_templates/layout.html index d85f075141..69e1a868c0 100644 --- a/doc/numpy/_templates/layout.html +++ b/doc/numpy/_templates/layout.html @@ -90,7 +90,7 @@

C++ Boost

+ alt="C++ Boost" src="{{ pathto('_static/bpl.png', 1) }}" border="0"> From 5f5f38fa8a510e43fc747422cfe7eab0c3daf403 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Sat, 25 Oct 2025 03:58:46 +0900 Subject: [PATCH 111/120] fix: fix quotation --- test/shared_ptr.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/shared_ptr.py b/test/shared_ptr.py index d250ae7eca..4ef88f78d8 100644 --- a/test/shared_ptr.py +++ b/test/shared_ptr.py @@ -38,7 +38,7 @@ 12 >>> try: modify(p) ... except TypeError: pass -... else: 'print(expected a TypeError)' +... else: print('expected a TypeError') >>> look(None) -1 >>> store(p) @@ -61,7 +61,7 @@ 13 >>> try: modify(z) ... except TypeError: pass -... else: 'print(expected a TypeError)' +... else: print('expected a TypeError') >>> Z.get() # should be None >>> store(z) @@ -84,7 +84,7 @@ 17 >>> try: modify(x) ... except TypeError: pass -... else: 'print(expected a TypeError)' +... else: print('expected a TypeError') >>> look(None) -1 >>> store(x) From 668bc7c106bf32aa64e05ab4f26d13a708971baf Mon Sep 17 00:00:00 2001 From: Anton Gladky Date: Tue, 28 Oct 2025 20:56:28 +0100 Subject: [PATCH 112/120] Include missing header boost/type_traits/is_unsigned.hpp During the Debian Packaging of new version it was found that this header is missing during the rebuild with GCC-15. --- include/boost/python/numpy/dtype.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/boost/python/numpy/dtype.hpp b/include/boost/python/numpy/dtype.hpp index 4673745e57..9438d79fdc 100644 --- a/include/boost/python/numpy/dtype.hpp +++ b/include/boost/python/numpy/dtype.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { namespace python { namespace numpy { From 97402f7925648ef433d0f1f979b9b422936dac31 Mon Sep 17 00:00:00 2001 From: Abhay Kumar Date: Fri, 6 Jun 2025 11:27:53 +0530 Subject: [PATCH 113/120] :bug: Fix broken link to Jamroot in example docs --- doc/tutorial.qbk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index d7c0cfa93e..197470013e 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -117,7 +117,7 @@ platforms. The complete list of Bjam executables can be found [h2 Let's Jam!] __jam__ -[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot +[@../example/Jamroot Here] is our minimalist Jamroot file. Simply copy the file and tweak [^use-project boost] to where your boost root directory is and you're OK. From cabb466057c53d1ff065384ff86c8a98719f3bc2 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Mon, 13 Oct 2025 20:59:57 -0700 Subject: [PATCH 114/120] Use strong reference APIs. For the free-threaded build, it is not safe use borrowed references. Another thread could deallocate the object and cause the reference to become invalid. Replace API calls that borrow references with strong reference APIs. --- src/dict.cpp | 8 ++++++++ src/object/function_doc_signature.cpp | 15 +++++++++++++-- src/wrapper.cpp | 20 ++++++++++++++------ 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/dict.cpp b/src/dict.cpp index 77d840d455..296bc21e9c 100644 --- a/src/dict.cpp +++ b/src/dict.cpp @@ -68,8 +68,16 @@ object dict_base::get(object_cref k) const { if (check_exact(this)) { +#ifdef Py_GIL_DISABLED + PyObject* result; + if (PyDict_GetItemRef(this->ptr(),k.ptr(),&result) < 0) { + throw_error_already_set(); + } + return object(detail::new_reference(result ? result : Py_None)); +#else PyObject* result = PyDict_GetItem(this->ptr(),k.ptr()); return object(detail::borrowed_reference(result ? result : Py_None)); +#endif } else { diff --git a/src/object/function_doc_signature.cpp b/src/object/function_doc_signature.cpp index 18d458698d..76b620dcb9 100644 --- a/src/object/function_doc_signature.cpp +++ b/src/object/function_doc_signature.cpp @@ -135,7 +135,15 @@ namespace boost { namespace python { namespace objects { str name(get_qualname(py_type)); if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) { // Qualify the type name if it is defined in a different module. - PyObject *type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__"); + PyObject *type_module_name; +#if PY_VERSION_HEX >= 0x030D0000 + if (PyDict_GetItemStringRef(py_type->tp_dict, "__module__", &type_module_name) < 0) { + throw_error_already_set(); + } +#else + type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__"); + Py_XINCREF(type_module_name); +#endif if ( type_module_name && PyObject_RichCompareBool( @@ -144,8 +152,11 @@ namespace boost { namespace python { namespace objects { Py_NE ) != 0 ) { - return str("%s.%s" % make_tuple(handle<>(borrowed(type_module_name)), name)); + str result = str("%s.%s" % make_tuple(handle<>(type_module_name), name)); + return result; } + // Clean up the strong reference if we didn't use it + Py_XDECREF(type_module_name); } return name; } else { diff --git a/src/wrapper.cpp b/src/wrapper.cpp index 8b1b884769..2b053d8311 100644 --- a/src/wrapper.cpp +++ b/src/wrapper.cpp @@ -21,20 +21,28 @@ namespace detail this->m_self, const_cast(name)))) ) { - PyObject* borrowed_f = 0; - + PyObject* class_f = 0; + if ( PyMethod_Check(m.get()) && PyMethod_GET_SELF(m.get()) == this->m_self && class_object->tp_dict != 0 ) { - borrowed_f = ::PyDict_GetItemString( +#if PY_VERSION_HEX >= 0x030D0000 + if (::PyDict_GetItemStringRef( + class_object->tp_dict, const_cast(name), &class_f) < 0) { + throw_error_already_set(); + } +#else + class_f = ::PyDict_GetItemString( class_object->tp_dict, const_cast(name)); - - + Py_XINCREF(class_f); +#endif } - if (borrowed_f != PyMethod_GET_FUNCTION(m.get())) + bool is_override = (class_f != PyMethod_GET_FUNCTION(m.get())); + Py_XDECREF(class_f); + if (is_override) return override(m); } } From 6f5f3b66074b27b44ddc5f1198003d0b01d31a52 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Thu, 30 Oct 2025 14:23:37 -0700 Subject: [PATCH 115/120] Add work-around to crash in ~object_base(). For the free-threaded build (and possibly the debug build), it is not safe to call Py_DECREF() if there is no valid Python thread-state. --- include/boost/python/object_core.hpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/boost/python/object_core.hpp b/include/boost/python/object_core.hpp index 16480d0d89..074360d415 100644 --- a/include/boost/python/object_core.hpp +++ b/include/boost/python/object_core.hpp @@ -419,6 +419,16 @@ inline api::object_base& api::object_base::operator=(api::object_base const& rhs inline api::object_base::~object_base() { +#ifdef Py_GIL_DISABLED + // This is a not very elegant fix for a problem that occurs with the + // free-threaded build of Python. If this is called when the interpreter + // has already been finalized, the thread-state can be null. Unlike the + // GIL-enabled build, Py_DECREF() requires a valid thread-state. This + // causes a memory leak, rather than crash, which seems preferable. + if (PyThreadState_GetUnchecked() == NULL) { + return; + } +#endif assert( Py_REFCNT(m_ptr) > 0 ); Py_DECREF(m_ptr); } From cfbefe893ca6254fd2377c4f6fcdacfd3b851680 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Mon, 13 Oct 2025 22:42:42 -0700 Subject: [PATCH 116/120] Use re-entrant mutex to protect global state. Add pymutex.hpp which implements a re-entrant mutex on top of Python's PyMutex. Add BOOST_PYTHON_LOCK_STATE() macro that uses RAII to lock mutable global state as required. --- include/boost/python/detail/pymutex.hpp | 103 ++++++++++++++++++++++++ src/converter/from_python.cpp | 7 +- src/converter/registry.cpp | 9 ++- src/converter/type_id.cpp | 6 +- src/errors.cpp | 22 ++++- src/object/inheritance.cpp | 6 ++ 6 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 include/boost/python/detail/pymutex.hpp diff --git a/include/boost/python/detail/pymutex.hpp b/include/boost/python/detail/pymutex.hpp new file mode 100644 index 0000000000..2d2e2d6266 --- /dev/null +++ b/include/boost/python/detail/pymutex.hpp @@ -0,0 +1,103 @@ +// Copyright 2025 Boost.Python Contributors +// 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 BOOST_PYTHON_DETAIL_PYMUTEX_HPP +#define BOOST_PYTHON_DETAIL_PYMUTEX_HPP + +#include +#ifdef Py_GIL_DISABLED +// needed for pymutex wrapper +#include +#include +#endif + +namespace boost { namespace python { namespace detail { + +#ifdef Py_GIL_DISABLED + +// Re-entrant wrapper around PyMutex for free-threaded Python +// Similar to _PyRecursiveMutex or threading.RLock +class pymutex { + PyMutex m_mutex; + std::atomic m_owner; + std::size_t m_level; + +public: + pymutex() : m_mutex({}), m_owner(0), m_level(0) {} + + // Non-copyable, non-movable + pymutex(const pymutex&) = delete; + pymutex& operator=(const pymutex&) = delete; + + void lock() { + unsigned long thread = PyThread_get_thread_ident(); + if (m_owner.load(std::memory_order_relaxed) == thread) { + m_level++; + return; + } + PyMutex_Lock(&m_mutex); + m_owner.store(thread, std::memory_order_relaxed); + // m_level should be 0 when we acquire the lock + } + + void unlock() { + unsigned long thread = PyThread_get_thread_ident(); + // Verify current thread owns the lock + if (m_owner.load(std::memory_order_relaxed) != thread) { + // This should never happen - programming error + return; + } + if (m_level > 0) { + m_level--; + return; + } + m_owner.store(0, std::memory_order_relaxed); + PyMutex_Unlock(&m_mutex); + } + + bool is_locked_by_current_thread() const { + unsigned long thread = PyThread_get_thread_ident(); + return m_owner.load(std::memory_order_relaxed) == thread; + } +}; + + +// RAII lock guard for pymutex +class pymutex_guard { + pymutex& m_mutex; + +public: + explicit pymutex_guard(pymutex& mutex) : m_mutex(mutex) { + m_mutex.lock(); + } + + ~pymutex_guard() { + m_mutex.unlock(); + } + + // Non-copyable, non-movable + pymutex_guard(const pymutex_guard&) = delete; + pymutex_guard& operator=(const pymutex_guard&) = delete; +}; + +// Global mutex for protecting all Boost.Python internal state +// Similar to pybind11's internals.mutex +BOOST_PYTHON_DECL pymutex& get_global_mutex(); + +// Macro for acquiring the global lock +// Similar to pybind11's PYBIND11_LOCK_INTERNALS +#define BOOST_PYTHON_LOCK_STATE() \ + ::boost::python::detail::pymutex_guard lock(::boost::python::detail::get_global_mutex()) + +#else + +// No-op macro when not in free-threaded mode +#define BOOST_PYTHON_LOCK_STATE() + +#endif // Py_GIL_DISABLED + +}}} // namespace boost::python::detail + +#endif // BOOST_PYTHON_DETAIL_PYMUTEX_HPP diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index f3989ba77f..53a149fa72 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -145,6 +146,8 @@ namespace inline bool visit(rvalue_from_python_chain const* chain) { + BOOST_PYTHON_LOCK_STATE(); + visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); if (p != visited.end() && *p == chain) return false; @@ -157,9 +160,11 @@ namespace { unvisit(rvalue_from_python_chain const* chain) : chain(chain) {} - + ~unvisit() { + BOOST_PYTHON_LOCK_STATE(); + visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); assert(p != visited.end()); visited.erase(p); diff --git a/src/converter/registry.cpp b/src/converter/registry.cpp index aa20c3f685..1b23dbef48 100644 --- a/src/converter/registry.cpp +++ b/src/converter/registry.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -112,9 +113,9 @@ registration::~registration() namespace // { typedef registration entry; - + typedef std::set registry_t; - + #ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND registry_t& entries() { @@ -181,6 +182,8 @@ namespace // entry* get(type_info type, bool is_shared_ptr = false) { + BOOST_PYTHON_LOCK_STATE(); + # ifdef BOOST_PYTHON_TRACE_REGISTRY registry_t::iterator p = entries().find(entry(type)); @@ -293,6 +296,8 @@ namespace registry registration const* query(type_info type) { + BOOST_PYTHON_LOCK_STATE(); + registry_t::iterator p = entries().find(entry(type)); # ifdef BOOST_PYTHON_TRACE_REGISTRY std::cout << "querying " << type diff --git a/src/converter/type_id.cpp b/src/converter/type_id.cpp index c6a8bf7a04..fafb13619c 100644 --- a/src/converter/type_id.cpp +++ b/src/converter/type_id.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -81,7 +82,7 @@ namespace { free_mem(char*p) : p(p) {} - + ~free_mem() { std::free(p); @@ -92,6 +93,7 @@ namespace bool cxxabi_cxa_demangle_is_broken() { + BOOST_PYTHON_LOCK_STATE(); static bool was_tested = false; static bool is_broken = false; if (!was_tested) { @@ -109,6 +111,8 @@ namespace detail { BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled) { + BOOST_PYTHON_LOCK_STATE(); + typedef std::vector< std::pair > mangling_map; diff --git a/src/errors.cpp b/src/errors.cpp index 34ea22f43e..7f6b1880d5 100644 --- a/src/errors.cpp +++ b/src/errors.cpp @@ -10,9 +10,21 @@ #include #include #include +#include namespace boost { namespace python { +#ifdef Py_GIL_DISABLED +namespace detail { + // Global mutex for protecting all Boost.Python internal state + pymutex& get_global_mutex() + { + static pymutex mutex; + return mutex; + } +} +#endif + error_already_set::~error_already_set() {} // IMPORTANT: this function may only be called from within a catch block! @@ -20,8 +32,13 @@ BOOST_PYTHON_DECL bool handle_exception_impl(function0 f) { try { - if (detail::exception_handler::chain) - return detail::exception_handler::chain->handle(f); + detail::exception_handler* handler_chain = nullptr; + { + BOOST_PYTHON_LOCK_STATE(); + handler_chain = detail::exception_handler::chain; + } + if (handler_chain) + return handler_chain->handle(f); f(); return false; } @@ -80,6 +97,7 @@ exception_handler::exception_handler(handler_function const& impl) : m_impl(impl) , m_next(0) { + BOOST_PYTHON_LOCK_STATE(); if (chain != 0) tail->m_next = this; else diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index a7b3156e41..44062875a4 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -4,6 +4,7 @@ // http://www.boost.org/LICENSE_1_0.txt) #include #include +#include #include #if _MSC_FULL_VER >= 13102171 && _MSC_FULL_VER <= 13102179 # include @@ -390,6 +391,8 @@ namespace inline void* convert_type(void* const p, class_id src_t, class_id dst_t, bool polymorphic) { + BOOST_PYTHON_LOCK_STATE(); + // Quickly rule out unregistered types index_entry* src_p = seek_type(src_t); if (src_p == 0) @@ -452,6 +455,8 @@ BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src_t, class_id dst_t BOOST_PYTHON_DECL void add_cast( class_id src_t, class_id dst_t, cast_function cast, bool is_downcast) { + BOOST_PYTHON_LOCK_STATE(); + // adding an edge will invalidate any record of unreachability in // the cache. static std::size_t expected_cache_len = 0; @@ -490,6 +495,7 @@ BOOST_PYTHON_DECL void add_cast( BOOST_PYTHON_DECL void register_dynamic_id_aux( class_id static_id, dynamic_id_function get_dynamic_id) { + BOOST_PYTHON_LOCK_STATE(); tuples::get(*demand_type(static_id)) = get_dynamic_id; } From fc68878e02bb2cb9a0e107a24daf890b5ffc4477 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Mon, 13 Oct 2025 20:59:37 -0700 Subject: [PATCH 117/120] Set the Py_MOD_GIL_NOT_USED flag on modules. This indicates that the free-threaded build of Python can keep the GIL disabled when the module is loaded. Without this module flag, importing the module will cause the GIL to be re-enabled. A warning is emitted if this happens. --- src/module.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/module.cpp b/src/module.cpp index 57675fa2df..707e433941 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -40,8 +40,14 @@ BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef& moduledef, void(*init_function)()) { + PyObject *mod = PyModule_Create(&moduledef); +#ifdef Py_GIL_DISABLED + if (mod != NULL) { + PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED); + } +#endif return init_module_in_scope( - PyModule_Create(&moduledef), + mod, init_function); } From 501356431631b3bcb10dd0a9336a5a05d2171889 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Thu, 6 Nov 2025 15:45:22 -0800 Subject: [PATCH 118/120] Add "nogil" option for BOOST_PYTHON_MODULE_INIT. Implement optional arguments for BOOST_PYTHON_MODULE_INIT and allow the boost::python::mod_gil_not_used() option. This sets the Py_MOD_GIL_NOT_USED flag for the extension module. To define a module that supports free-threaded Python, define it like this: BOOST_PYTHON_MODULE(my_module, boost::python::mod_gil_not_used()) { ... } --- include/boost/python/module_init.hpp | 75 ++++++++++++++++++++++++++-- src/module.cpp | 5 +- test/fabscript | 1 + test/module_nogil.cpp | 25 ++++++++++ test/module_nogil.py | 29 +++++++++++ 5 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 test/module_nogil.cpp create mode 100644 test/module_nogil.py diff --git a/include/boost/python/module_init.hpp b/include/boost/python/module_init.hpp index 7fe5a1c8a2..390db82cf4 100644 --- a/include/boost/python/module_init.hpp +++ b/include/boost/python/module_init.hpp @@ -11,11 +11,41 @@ # ifndef BOOST_PYTHON_MODULE_INIT -namespace boost { namespace python { namespace detail { +namespace boost { namespace python { + +#ifdef HAS_CXX11 +// Use to activate the Py_MOD_GIL_NOT_USED flag. +class mod_gil_not_used { +public: + explicit mod_gil_not_used(bool flag = true) : flag_(flag) {} + bool flag() const { return flag_; } + +private: + bool flag_; +}; + +namespace detail { + +inline bool gil_not_used_option() { return false; } +template +bool gil_not_used_option(F &&, O &&...o); +template +inline bool gil_not_used_option(mod_gil_not_used f, O &&...o) { + return f.flag() || gil_not_used_option(o...); +} +template +inline bool gil_not_used_option(F &&, O &&...o) { + return gil_not_used_option(o...); +} + +} +#endif // HAS_CXX11 + +namespace detail { # if PY_VERSION_HEX >= 0x03000000 -BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)()); +BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)(), bool gil_not_used = false); #else @@ -27,7 +57,37 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)()); # if PY_VERSION_HEX >= 0x03000000 -# define _BOOST_PYTHON_MODULE_INIT(name) \ +# ifdef HAS_CXX11 +# define _BOOST_PYTHON_MODULE_INIT(name, ...) \ + PyObject* BOOST_PP_CAT(PyInit_, name)() \ + { \ + static PyModuleDef_Base initial_m_base = { \ + PyObject_HEAD_INIT(NULL) \ + 0, /* m_init */ \ + 0, /* m_index */ \ + 0 /* m_copy */ }; \ + static PyMethodDef initial_methods[] = { { 0, 0, 0, 0 } }; \ + \ + static struct PyModuleDef moduledef = { \ + initial_m_base, \ + BOOST_PP_STRINGIZE(name), \ + 0, /* m_doc */ \ + -1, /* m_size */ \ + initial_methods, \ + 0, /* m_reload */ \ + 0, /* m_traverse */ \ + 0, /* m_clear */ \ + 0, /* m_free */ \ + }; \ + \ + return boost::python::detail::init_module( \ + moduledef, BOOST_PP_CAT(init_module_, name), \ + boost::python::detail::gil_not_used_option(__VA_ARGS__) ); \ + } \ + void BOOST_PP_CAT(init_module_, name)() + +# else // !HAS_CXX11 +# define _BOOST_PYTHON_MODULE_INIT(name) \ PyObject* BOOST_PP_CAT(PyInit_, name)() \ { \ static PyModuleDef_Base initial_m_base = { \ @@ -53,6 +113,7 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)()); moduledef, BOOST_PP_CAT(init_module_, name) ); \ } \ void BOOST_PP_CAT(init_module_, name)() +# endif // HAS_CXX11 # else @@ -66,9 +127,15 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)()); # endif -# define BOOST_PYTHON_MODULE_INIT(name) \ +# if defined(HAS_CXX11) && (PY_VERSION_HEX >= 0x03000000) +# define BOOST_PYTHON_MODULE_INIT(name, ...) \ + void BOOST_PP_CAT(init_module_,name)(); \ +extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name, __VA_ARGS__) +# else +# define BOOST_PYTHON_MODULE_INIT(name) \ void BOOST_PP_CAT(init_module_,name)(); \ extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name) +# endif // HAS_CXX11 && Python 3 # endif diff --git a/src/module.cpp b/src/module.cpp index 707e433941..c32f4187bc 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -38,11 +38,12 @@ BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char #if PY_VERSION_HEX >= 0x03000000 -BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef& moduledef, void(*init_function)()) +BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef& moduledef, + void(*init_function)(), bool gil_not_used) { PyObject *mod = PyModule_Create(&moduledef); #ifdef Py_GIL_DISABLED - if (mod != NULL) { + if (mod != NULL && gil_not_used) { PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED); } #endif diff --git a/test/fabscript b/test/fabscript index a002fb2bf0..7cf22f9c09 100644 --- a/test/fabscript +++ b/test/fabscript @@ -68,6 +68,7 @@ for t in [('injected',), ('raw_ctor',), ('exception_translator',), ('module_init_exception',), + ('module_nogil',), ('test_enum', ['enum_ext']), ('test_cltree', ['cltree']), ('newtest', ['m1', 'm2']), diff --git a/test/module_nogil.cpp b/test/module_nogil.cpp new file mode 100644 index 0000000000..331a73cf31 --- /dev/null +++ b/test/module_nogil.cpp @@ -0,0 +1,25 @@ +// Test for BOOST_PYTHON_MODULE with optional mod_gil_not_used argument + +#include +#include + +// Simple function to export +int get_value() { + return 1234; +} + +#if defined(HAS_CXX11) && (PY_VERSION_HEX >= 0x03000000) +// C++11 build with Python 3: test with mod_gil_not_used option +BOOST_PYTHON_MODULE(module_nogil_ext, boost::python::mod_gil_not_used()) +{ + using namespace boost::python; + def("get_value", get_value); +} +#else +// C++98 build or Python 2: test without optional arguments +BOOST_PYTHON_MODULE(module_nogil_ext) +{ + using namespace boost::python; + def("get_value", get_value); +} +#endif diff --git a/test/module_nogil.py b/test/module_nogil.py new file mode 100644 index 0000000000..c035436014 --- /dev/null +++ b/test/module_nogil.py @@ -0,0 +1,29 @@ +""" +>>> from module_nogil_ext import * +>>> get_value() +1234 +>>> import sys, sysconfig +>>> Py_GIL_DISABLED = bool(sysconfig.get_config_var('Py_GIL_DISABLED')) +>>> if Py_GIL_DISABLED and sys._is_gil_enabled(): +... print('GIL is enabled and should not be') +... else: +... print('okay') +okay +""" + +from __future__ import print_function + +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) From e89f86b74f7cdd5682c1ea4e45a809471a11d7f0 Mon Sep 17 00:00:00 2001 From: Neil Schemenauer Date: Tue, 11 Nov 2025 10:04:47 -0800 Subject: [PATCH 119/120] Update Linux CI scripts, more Python versions. Update scripts to use actions/setup-python to install different Python versions. Add run-faber.sh and get-py-env.py scripts. Add test-ubuntu-py-ver.yml CI script to test with different Python versions. --- .github/get-py-env.py | 65 +++++++++++++++++++++++++++ .github/run-faber.sh | 46 +++++++++++++++++++ .github/workflows/test-ubuntu-py2.yml | 58 ++++++++++++++++++++++++ .github/workflows/test-ubuntu.yml | 58 +++++++++++------------- 4 files changed, 194 insertions(+), 33 deletions(-) create mode 100755 .github/get-py-env.py create mode 100755 .github/run-faber.sh create mode 100644 .github/workflows/test-ubuntu-py2.yml diff --git a/.github/get-py-env.py b/.github/get-py-env.py new file mode 100755 index 0000000000..a6c41460d8 --- /dev/null +++ b/.github/get-py-env.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Determine info about the Python install and write shell code to stdout, to +# set env variables. This will set the variables PY_LDFLAGS, PY_CFLAGS and +# PY_INC_PATH. +# +# The python3-config tool is used as the source of this info. In theory we +# could use sysconfig as well but the setup-python action from github appears +# to patch python3-config but not patch the sysconfig info. +# +# Usage: +# eval $(python3 get-py-env.py) + +import os +import re +import subprocess + + +def get_output(cmd): + rv = subprocess.run( + cmd, + capture_output=True, # Capture stdout and stderr + text=True, # Decode output as text (UTF-8) + check=True, # Raise an error if the command fails + ) + return rv.stdout + + +def extract_flags(cmd, prefix): + flags = [] + for part in get_output(cmd).split(): + part = part.strip() + if part.startswith(prefix): + flags.append(part) + return ' '.join(flags) + + +def find_python_h(): + """Find the include path that has Python.h contained inside. + We could use INCLUDEPY from sysconfig but github patches + python3-config but not the sysconfig info (after moving the + install). + """ + c_flags = extract_flags(['python3-config', '--cflags'], '-I') + for part in c_flags.split(): + m = re.search(r'-I(\S+)', part) + if not m: + continue + inc_path = m.group(1) + if os.path.exists(os.path.join(inc_path, 'Python.h')): + return inc_path + raise SystemExit('cannot find Python.h') + + +def main(): + ld_flags = extract_flags(['python3-config', '--ldflags'], '-L') + c_flags = extract_flags(['python3-config', '--cflags'], '-I') + include_path = find_python_h() + print(f'PY_LDFLAGS="{ld_flags}"') + print(f'PY_CFLAGS="{c_flags}"') + print(f'PY_INC_PATH="{include_path}"') + + +if __name__ == '__main__': + main() diff --git a/.github/run-faber.sh b/.github/run-faber.sh new file mode 100755 index 0000000000..5cb78be6dd --- /dev/null +++ b/.github/run-faber.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +set -eu + +echo "cxx version: $CXX $($CXX --version)" +echo "cxx std: $CXX_STD" +echo "python3 path: $(which python3)" +echo "python3 version: $(python3 --version)" + +if ! which faber > /dev/null; then + echo "Installing faber..." + python3 -m pip install --upgrade pip + python3 -m pip install -U faber +fi +echo "faber version: $(faber -v)" + +# find and set PY_LDFLAGS and PY_INC_PATH +eval $(python3 .github/get-py-env.py) + +echo "PY_INC_PATH=$PY_INC_PATH" +echo "PY_LDFLAGS=$PY_LDFLAGS" + +case $(python3-config --abiflags) in + *t*) + # When running with free-threaded, we always want to disable the GIL + # even for extensions without the mod_gil_not_used() flag + export PYTHON_GIL=0 + ;; +esac + +# this could be set by LD_LIBRARY_PATH but faber overrides it +prefix=$(python3-config --prefix) +echo "${prefix}/lib" > /etc/ld.so.conf.d/boost-ci.conf && ldconfig + +sed -e "s/\$PYTHON/python3/g" .ci/faber > $HOME/.faber + +faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name="${CXX}" \ + cxxflags="-std=${CXX_STD}" \ + cppflags="-std=${CXX_STD}" \ + include="${PY_INC_PATH}" \ + ldflags="${PY_LDFLAGS}" \ + -j`nproc` \ + "$@" diff --git a/.github/workflows/test-ubuntu-py2.yml b/.github/workflows/test-ubuntu-py2.yml new file mode 100644 index 0000000000..801664c105 --- /dev/null +++ b/.github/workflows/test-ubuntu-py2.yml @@ -0,0 +1,58 @@ +name: Test Ubuntu, Python 2.x + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + python: [python] + cxx: [g++] + std: [c++11] + include: + # Add the appropriate docker image for each compiler. + # The images from teeks99/boost-python-test already have boost::python + # pre-reqs installed, see: + # https://github.com/teeks99/boost-python-test-docker + - cxx: g++ + docker-img: teeks99/boost-python-test:gcc-15_1.89.0 + + container: + image: ${{ matrix.docker-img }} + + steps: + - uses: actions/checkout@v5 + + - name: setup prerequisites + run: | + # Warning: this is not necessarily the same Python version as the one configured above ! + python3 -m pip install -U faber --break-system-packages + - name: build + run: | + ${{ matrix.python }} --version + ${{ matrix.cxx }} --version + faber -v + sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`nproc` + - name: test + run: | + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`nproc` \ + test.report diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index 6f94c2d186..abb0f2d59a 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -1,6 +1,10 @@ +# Test on Ubuntu with various compiler and language standard versions. name: Test Ubuntu -on: [push, pull_request] +on: + push: + pull_request: + workflow_dispatch: jobs: build: @@ -9,49 +13,37 @@ jobs: strategy: fail-fast: false matrix: - python: [python, python3] + python-version: ['3.14'] cxx: [g++, clang++] std: [c++11, c++14, c++17] include: - # Add the appropriate docker image for each compiler. - # The images from teeks99/boost-python-test already have boost::python - # pre-reqs installed, see: - # https://github.com/teeks99/boost-python-test-docker - - cxx: clang++ - docker-img: teeks99/boost-python-test:clang-21_1.89.0 - - cxx: g++ - docker-img: teeks99/boost-python-test:gcc-15_1.89.0 + # Also test with free-threaded build of Python + - python-version: '3.14t' + cxx: clang++ + std: c++17 container: - image: ${{ matrix.docker-img }} + # Add the appropriate docker image for the compiler. + # The images from teeks99/boost-python-test already have boost::python + # pre-reqs installed, see: + # https://github.com/teeks99/boost-python-test-docker + image: ${{ matrix.cxx == 'g++' && + 'teeks99/boost-python-test:gcc-15_1.89.0' || + 'teeks99/boost-python-test:clang-21_1.89.0' }} steps: - uses: actions/checkout@v5 - + - name: setup python + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} - name: setup prerequisites run: | - # Warning: this is not necessarily the same Python version as the one configured above ! - python3 -m pip install -U faber --break-system-packages + echo "CXX=${{ matrix.cxx }}" >> "$GITHUB_ENV" + echo "CXX_STD=${{ matrix.std }}" >> "$GITHUB_ENV" - name: build run: | - ${{ matrix.python }} --version - ${{ matrix.cxx }} --version - faber -v - sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber - faber \ - --with-boost-include=${BOOST_PY_DEPS} \ - --builddir=build \ - cxx.name=${{ matrix.cxx }} \ - cxxflags=-std=${{ matrix.std }} \ - cppflags=-std=${{ matrix.std }} \ - -j`nproc` + .github/run-faber.sh - name: test run: | - faber \ - --with-boost-include=${BOOST_PY_DEPS} \ - --builddir=build \ - cxx.name=${{ matrix.cxx }} \ - cxxflags=-std=${{ matrix.std }} \ - cppflags=-std=${{ matrix.std }} \ - -j`nproc` \ - test.report + .github/run-faber.sh test.report From 32da86df269fb8f7ef777ddd8c3424d854e94455 Mon Sep 17 00:00:00 2001 From: Stefan Seefeld Date: Tue, 2 Dec 2025 08:38:34 -0500 Subject: [PATCH 120/120] Improve test coverage. --- .github/workflows/test-ubuntu-py2.yml | 58 --------------------------- .github/workflows/test-ubuntu.yml | 49 +++++++++++++++++++++- 2 files changed, 47 insertions(+), 60 deletions(-) delete mode 100644 .github/workflows/test-ubuntu-py2.yml diff --git a/.github/workflows/test-ubuntu-py2.yml b/.github/workflows/test-ubuntu-py2.yml deleted file mode 100644 index 801664c105..0000000000 --- a/.github/workflows/test-ubuntu-py2.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Test Ubuntu, Python 2.x - -on: - push: - pull_request: - workflow_dispatch: - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - python: [python] - cxx: [g++] - std: [c++11] - include: - # Add the appropriate docker image for each compiler. - # The images from teeks99/boost-python-test already have boost::python - # pre-reqs installed, see: - # https://github.com/teeks99/boost-python-test-docker - - cxx: g++ - docker-img: teeks99/boost-python-test:gcc-15_1.89.0 - - container: - image: ${{ matrix.docker-img }} - - steps: - - uses: actions/checkout@v5 - - - name: setup prerequisites - run: | - # Warning: this is not necessarily the same Python version as the one configured above ! - python3 -m pip install -U faber --break-system-packages - - name: build - run: | - ${{ matrix.python }} --version - ${{ matrix.cxx }} --version - faber -v - sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber - faber \ - --with-boost-include=${BOOST_PY_DEPS} \ - --builddir=build \ - cxx.name=${{ matrix.cxx }} \ - cxxflags=-std=${{ matrix.std }} \ - cppflags=-std=${{ matrix.std }} \ - -j`nproc` - - name: test - run: | - faber \ - --with-boost-include=${BOOST_PY_DEPS} \ - --builddir=build \ - cxx.name=${{ matrix.cxx }} \ - cxxflags=-std=${{ matrix.std }} \ - cppflags=-std=${{ matrix.std }} \ - -j`nproc` \ - test.report diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml index abb0f2d59a..31637de5ef 100644 --- a/.github/workflows/test-ubuntu.yml +++ b/.github/workflows/test-ubuntu.yml @@ -17,6 +17,21 @@ jobs: cxx: [g++, clang++] std: [c++11, c++14, c++17] include: + - python-version: '2.7' + cxx: g++ + std: c++11 + - python-version: '3.10' + cxx: g++ + std: c++17 + - python-version: '3.11' + cxx: g++ + std: c++17 + - python-version: '3.12' + cxx: g++ + std: c++17 + - python-version: '3.13' + cxx: g++ + std: c++17 # Also test with free-threaded build of Python - python-version: '3.14t' cxx: clang++ @@ -34,16 +49,46 @@ jobs: steps: - uses: actions/checkout@v5 - name: setup python + if: "${{ matrix.python-version != '2.7' }}" uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: setup prerequisites run: | + # Warning: this is not necessarily the same Python version as the one configured above ! + python3 -m pip install -U faber --break-system-packages echo "CXX=${{ matrix.cxx }}" >> "$GITHUB_ENV" echo "CXX_STD=${{ matrix.std }}" >> "$GITHUB_ENV" - - name: build + - name: build-py2 + if: "${{ matrix.python-version == '2.7' }}" + run: | + python --version + ${{ matrix.cxx }} --version + faber -v + sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`nproc` + - name: build-py3 + if: "${{ matrix.python-version != '2.7' }}" run: | .github/run-faber.sh - - name: test + - name: test-py2 + if: "${{ matrix.python-version == '2.7' }}" + run: | + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`nproc` \ + test.report + - name: test-py3 + if: "${{ matrix.python-version != '2.7' }}" run: | .github/run-faber.sh test.report