2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-20 16:52:15 +00:00

Compare commits

...

51 Commits

Author SHA1 Message Date
Stefan Seefeld
8b7a8ccc85 Test multiple Python versions. 2025-03-18 16:00:49 -04:00
Aditya Pillai
3e7be69e1e Conditionally use Py_REFCNT 2025-03-10 15:10:12 -04:00
Aditya Pillai
cbdf1ce2a1 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.
2025-03-10 15:10:12 -04:00
Stefan Seefeld
4fe3403584 Make sure to pass C++ version to preprocessor as well. 2025-02-01 22:55:02 -05:00
Stefan Seefeld
b1b43f1e1a Fix homebrew include path. 2025-02-01 22:55:02 -05:00
Peter Dimov
7b1960446b Merge pull request #470 from boostorg/pr/fix-iterator-detail
Replace use of boost/iterator/detail/enable_if.hpp
2025-02-01 19:35:16 +02:00
Peter Dimov
2dc5a92727 Replace use of boost/iterator/detail/enable_if.hpp 2025-01-28 02:27:49 +02:00
sdarwin
4fc3afa3ac Support newer version of Sphinx 2024-10-10 09:28:59 -04:00
Vitaly Buka
ff0ae9b29d dynamic_cast before destructor
Call to the destructor ends lifetime of the object, including vptr
used by dynamic_cast.
2024-09-22 12:30:12 -04:00
Daniel Laügt
b988d70207 Alignment fixes 2024-09-21 21:56:41 -04:00
Stefan Seefeld
b3a28d7033 Use the expected return type. 2024-09-18 21:09:05 -04:00
Stefan Seefeld
3ea0cb8501 Upgrade CI platforms. 2024-09-18 21:09:05 -04:00
Jakob van Santen
95e53011d8 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
2024-09-18 10:36:45 -04:00
Jakob van Santen
301256cf1e Avoid setting __doc__ on instance methods 2024-09-18 10:36:45 -04:00
Jakob van Santen
c76d67ef3f Ensure that virtual default implementation has the same kwargs as dispatcher 2024-09-17 17:07:44 -04:00
Jakob van Santen
0102b31945 Unwrap back_reference in get_pytype()
This prevents back_reference parameters from decaying to "object" in py signatures
2024-09-17 17:07:44 -04:00
Jakob van Santen
4c6f40fb82 Add generated docstrings to property fget/fset 2024-09-17 17:07:44 -04:00
Jakob van Santen
d1910f3d65 Avoid degrading slice to object in generated sig 2024-09-17 17:07:44 -04:00
Jakob van Santen
c4e3b13dc2 Use qualname for enum repr 2024-09-17 17:07:44 -04:00
Jakob van Santen
a498e2458c Qualify types defined in other modules 2024-09-17 17:07:44 -04:00
Jakob van Santen
7a3cc07042 Emit qualfied names in docstrings 2024-09-17 17:07:44 -04:00
Jakob van Santen
58b1a010bb Set __qualname__ for Python >= 3.3 2024-09-17 17:07:44 -04:00
Rene Rivera
8ca8724ad9 Update build deps. 2024-08-18 13:16:00 -04:00
Rene Rivera
5a8d096135 Split b2 dependencies into public and private. 2024-08-18 13:16:00 -04:00
Rene Rivera
30bdbf3ae2 Move inter-lib dependencies to a project variable and into the build targets. 2024-08-18 13:16:00 -04:00
Rene Rivera
5a07cdb96b Bump B2 require to 5.2 2024-08-18 13:16:00 -04:00
Rene Rivera
06fa956fe8 Add requires-b2 check to top-level build file. 2024-08-18 13:16:00 -04:00
Rene Rivera
9ab1742c46 Add missing NO_LIB usage requirements. 2024-08-18 13:16:00 -04:00
Rene Rivera
071b0bc964 Switch to library requirements instead of source. As source puts extra source in install targets. 2024-08-18 13:16:00 -04:00
Rene Rivera
d8d9861036 Put back removing qualified boostcpp tag. As we need it until the Jamroot removes the qualified tag. 2024-08-18 13:16:00 -04:00
Rene Rivera
f6d20e1099 Make the library modular usable. 2024-08-18 13:16:00 -04:00
Billy K. Poon
99a5352b5c Another fix for numpy 2.0
- Compare pointers directly instead of using PyArray_EquivTypes
2024-07-16 14:15:12 -04:00
Konstantin Podsvirov
1fed0824ad Fix typo in numpy tutorial 2024-07-01 15:29:32 -04:00
Alexis DUBURCQ
0474de0f6c Support numpy 2.0.0b1 2024-05-06 09:51:13 +02:00
Peter Dimov
6c3f3ecacf Normalize static/dynamic link macros and avoid redefinition warnings 2023-12-22 08:14:53 -05:00
Stefan Seefeld
47d5bc76f6 Revert "Remove obsolete Jamfile" 2022-09-05 21:43:23 -04:00
Stefan Seefeld
508da1d198 Fix windows CI builds. 2022-08-24 13:02:31 -04:00
Stefan Seefeld
271bcea8bf Don't attempt to deploy documentation from PRs. 2022-08-24 13:02:31 -04:00
Stefan Seefeld
fdd3e8b2c1 Remove obsolete Jamfile 2022-08-24 13:02:31 -04:00
Victor Stinner
a218babc8d 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
2022-04-26 09:42:26 -04:00
Denis Arnaud
41e208ecb5 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.
2022-03-19 13:06:49 -04:00
Hajo Kirchhoff
f028aa4076 -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. 2021-08-10 12:25:40 -04:00
Hajo Kirchhoff
a060d43bf2 -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. 2021-08-10 12:25:40 -04:00
Stefan Seefeld
8dd1511773 Use the /python//numpy target instead of [ numpy.include ] (fixes #361) 2021-07-04 15:29:43 -04:00
Peter Dimov
909a4d1530 Merge branch 'master' into develop 2021-06-10 02:46:19 +03:00
TaWeiTu
aee2667407 Fix deprecated usage of <boost/bind.hpp>
Replace <boost/bind.hpp> with <boost/bind/bind.hpp> and use namespace
boost::placeholders when necessary.
2021-06-09 07:16:19 -04:00
Peter Dimov
209179fa09 Add CMakeLists.txt 2021-06-04 03:10:21 +03:00
Stefan Seefeld
5e77eabb63 Revert previous commit until 'Boost.Build' is ready. 2021-05-26 07:46:42 -04:00
Peter Dimov
ecda18f01e Use the /python//numpy target instead of [ numpy.include ] (fixes #361) 2021-05-24 18:54:56 -04:00
Stefan Seefeld
2a82afdf6d Upgrade base image & build prerequisites. 2021-04-30 22:59:25 -04:00
Stefan Seefeld
aca3c80c4f Respect alignment of by-value storage. 2021-04-30 22:59:25 -04:00
52 changed files with 780 additions and 212 deletions

View File

@@ -1,6 +1,6 @@
name: deploy documentation name: deploy documentation
on: [push, pull_request] on: [push]
jobs: jobs:
deploy: deploy:

View File

@@ -9,14 +9,14 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: [3.6] python-version: ['3.8.10', '3.12']
cxx: [clang++] 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: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: setup python - name: setup python
uses: actions/setup-python@v2 uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: setup prerequisites - name: setup prerequisites
@@ -28,18 +28,23 @@ jobs:
run: | run: |
python --version python --version
${{ matrix.cxx }} --version ${{ matrix.cxx }} --version
brew info boost
faber -v faber -v
sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber
faber \ faber \
--with-boost-include=$(brew --prefix boost)/include \
--builddir=build \ --builddir=build \
cxx.name=${{ matrix.cxx }} \ cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \ cxxflags=-std=${{ matrix.std }} \
cppflags=-std=${{ matrix.std }} \
-j`sysctl -n hw.ncpu` -j`sysctl -n hw.ncpu`
- name: test - name: test
run: | run: |
faber \ faber \
--with-boost-include=$(brew --prefix boost)/include \
--builddir=build\ --builddir=build\
cxx.name=${{ matrix.cxx }} \ cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \ cxxflags=-std=${{ matrix.std }} \
cppflags=-std=${{ matrix.std }} \
-j`sysctl -n hw.ncpu` \ -j`sysctl -n hw.ncpu` \
test.report test.report

View File

@@ -18,15 +18,15 @@ jobs:
# pre-reqs installed, see: # pre-reqs installed, see:
# https://github.com/teeks99/boost-python-test-docker # https://github.com/teeks99/boost-python-test-docker
- cxx: clang++ - 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++ - 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: container:
image: ${{ matrix.docker-img }} image: ${{ matrix.docker-img }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: build - name: build
run: | run: |
@@ -39,6 +39,7 @@ jobs:
--builddir=build \ --builddir=build \
cxx.name=${{ matrix.cxx }} \ cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \ cxxflags=-std=${{ matrix.std }} \
cppflags=-std=${{ matrix.std }} \
-j`nproc` -j`nproc`
- name: test - name: test
run: | run: |
@@ -47,5 +48,6 @@ jobs:
--builddir=build \ --builddir=build \
cxx.name=${{ matrix.cxx }} \ cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \ cxxflags=-std=${{ matrix.std }} \
cppflags=-std=${{ matrix.std }} \
-j`nproc` \ -j`nproc` \
test.report test.report

View File

@@ -11,20 +11,30 @@ jobs:
python-version: [3.7] python-version: [3.7]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- uses: actions/setup-python@v2 - uses: actions/setup-python@v5
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- uses: microsoft/setup-msbuild@v1.1
- name: setup boost prerequisites - name: setup boost prerequisites
uses: lukka/run-vcpkg@v6 uses: lukka/run-vcpkg@v6
with: with:
vcpkgGitCommitId: '8a9a97315aefb3f8bc5d81bf66ca0025938b9c91' vcpkgGitCommitId: '88b1071e39f13b632644d9d953738d345a4ac055'
vcpkgDirectory: '${{ runner.workspace }}/vcpkg' vcpkgDirectory: '${{ runner.workspace }}/vcpkg'
vcpkgTriplet: x64-windows 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 - name: setup faber
#shell: 'bash'
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
python -m pip install setuptools faber numpy python -m pip install setuptools faber numpy

176
CMakeLists.txt Normal file
View File

@@ -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()

41
build.jam Normal file
View File

@@ -0,0 +1,41 @@
# 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)
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/iterator//boost_iterator
/boost/lexical_cast//boost_lexical_cast
/boost/mpl//boost_mpl
/boost/numeric_conversion//boost_numeric_conversion
/boost/preprocessor//boost_preprocessor
/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
<include>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
;

View File

@@ -30,14 +30,34 @@ else
; ;
} }
project boost/python 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 : source-location ../src
: common-requirements <library>$(boost_dependencies)
: requirements <library>$(boost_dependencies_private)
; ;
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } } rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
rule unless ( 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 ; } } 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 lib boost_python
: # sources : # sources
list.cpp list.cpp
@@ -92,8 +112,9 @@ lib boost_python
[ unless [ python.configured ] : <build>no ] [ unless [ python.configured ] : <build>no ]
<dependency>config-warning <dependency>config-warning
<python-debugging>on:<define>BOOST_DEBUG_PYTHON <python-debugging>on:<define>BOOST_DEBUG_PYTHON
-<tag>@%boostcpp.tag
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag -<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@python-tag <tag>@tag
<conditional>@python.require-py <conditional>@python.require-py
: # default build : # default build
@@ -101,8 +122,20 @@ lib boost_python
: # usage requirements : # usage requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB <link>static:<define>BOOST_PYTHON_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON <python-debugging>on:<define>BOOST_DEBUG_PYTHON
<define>BOOST_PYTHON_NO_LIB
; ;
}
else
{
alias boost_python : config-warning ;
}
if [ python.configured ] && [ python.numpy ]
{
numpy-include = [ python.numpy-include ] ; numpy-include = [ python.numpy-include ] ;
lib boost_numpy lib boost_numpy
: # sources : # sources
@@ -117,11 +150,12 @@ lib boost_numpy
<define>BOOST_NUMPY_SOURCE <define>BOOST_NUMPY_SOURCE
[ cond [ python.numpy ] : <library>/python//python_for_extensions ] [ cond [ python.numpy ] : <library>/python//python_for_extensions ]
[ unless [ python.numpy ] : <build>no ] [ unless [ python.numpy ] : <build>no ]
<include>$(numpy-include) <library>/python//numpy
<library>boost_python <library>boost_python
<python-debugging>on:<define>BOOST_DEBUG_PYTHON <python-debugging>on:<define>BOOST_DEBUG_PYTHON
-<tag>@%boostcpp.tag
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag -<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@python-tag <tag>@tag
<conditional>@python.require-py <conditional>@python.require-py
: # default build : # default build
@@ -129,39 +163,13 @@ lib boost_numpy
: # usage requirements : # usage requirements
<link>static:<define>BOOST_NUMPY_STATIC_LIB <link>static:<define>BOOST_NUMPY_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON <python-debugging>on:<define>BOOST_DEBUG_PYTHON
<define>BOOST_NUMPY_NO_LIB
; ;
# 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 else
{ {
# When Python isn't configured, the above `boost-install` is not executed, alias boost_numpy : config-warning ;
# 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 ;
} }

View File

@@ -714,3 +714,23 @@ span.purple { color: purple; }
span.gold { color: gold; } span.gold { color: gold; }
span.silver { color: silver; } /* lighter gray */ span.silver { color: silver; } /* lighter gray */
span.gray { color: #808080; } /* light 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;
}

View File

@@ -49,6 +49,9 @@
{%- for scriptfile in script_files %} {%- for scriptfile in script_files %}
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script> <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
{%- endfor %} {%- endfor %}
<script data-url_root="{{ pathto('', 1) }}" id="documentation_options" src="{{ pathto('', 1) }}_static/documentation_options.js"></script>
<script src="{{ pathto('', 1) }}_static/searchtools.js"></script>
<script src="{{ pathto('', 1) }}_static/language_data.js"></script>
{%- if use_opensearch %} {%- if use_opensearch %}
<link rel="search" type="application/opensearchdescription+xml" <link rel="search" type="application/opensearchdescription+xml"
title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}"

View File

@@ -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) ; list_for_dtype.append(for_custom_dtype) ;
np::dtype custom_dtype = np::dtype(list_for_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); np::ndarray new_array = np::zeros(shape,custom_dtype);
} }

View File

@@ -3,7 +3,7 @@
# Examples # Examples
This directory contains various examples using Boost.Python. 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. or in any of the subdirectories.
You may need to adjust the paths in the Jamroot file if Boost.Python You may need to adjust the paths in the Jamroot file if Boost.Python
is not installed in a default location. is not installed in a default location.

View File

@@ -59,7 +59,7 @@ call_method(PyObject* self, char const* name
) )
{ {
PyObject* const result = PyObject* const result =
PyEval_CallMethod( PyObject_CallMethod(
self self
, const_cast<char*>(name) , const_cast<char*>(name)
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") , const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")

View File

@@ -372,10 +372,11 @@ class class_ : public objects::class_base
{ {
typedef typename api::is_object_operators<F>::type is_obj_or_proxy; typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl( return objects::add_doc(
this->make_fn_impl(
detail::unwrap_wrapper((W*)0) detail::unwrap_wrapper((W*)0)
, f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>() , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer<F>()
); ), NULL);
} }
template <class F> template <class F>
@@ -383,10 +384,11 @@ class class_ : public objects::class_base
{ {
typedef typename api::is_object_operators<F>::type is_obj_or_proxy; typedef typename api::is_object_operators<F>::type is_obj_or_proxy;
return this->make_fn_impl( return objects::add_doc(
this->make_fn_impl(
detail::unwrap_wrapper((W*)0) detail::unwrap_wrapper((W*)0)
, f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>() , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer<F>()
); ), NULL);
} }
template <class T, class F> template <class T, class F>

View File

@@ -81,9 +81,9 @@ inline object_manager_ref_arg_from_python<Ref>::object_manager_ref_arg_from_pyth
# if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 # if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243
// needed for warning suppression // needed for warning suppression
python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x); python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x);
python::detail::construct_referent<Ref>(&m_result.bytes, x_); python::detail::construct_referent<Ref>(m_result.bytes, x_);
# else # else
python::detail::construct_referent<Ref>(&m_result.bytes, (python::detail::borrowed_reference)x); python::detail::construct_referent<Ref>(m_result.bytes, (python::detail::borrowed_reference)x);
# endif # endif
} }

View File

@@ -9,7 +9,7 @@
# include <boost/python/converter/registered.hpp> # include <boost/python/converter/registered.hpp>
# include <boost/python/detail/unwind_type.hpp> # include <boost/python/detail/unwind_type.hpp>
# include <boost/python/detail/type_traits.hpp> # include <boost/python/detail/type_traits.hpp>
# include <boost/python/back_reference.hpp>
namespace boost { namespace python { namespace boost { namespace python {
@@ -46,6 +46,12 @@ inline python::type_info unwind_type_id_(boost::type<T>* = 0, mpl::false_ * =0)
return boost::python::detail::unwind_type<unwind_type_id_helper, T> (); return boost::python::detail::unwind_type<unwind_type_id_helper, T> ();
} }
template <class T>
inline python::type_info unwind_type_id_(boost::type<back_reference<T> >* = 0, mpl::false_ * =0)
{
return boost::python::detail::unwind_type<unwind_type_id_helper, T> ();
}
inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0) inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0)
{ {
return type_id<void>(); return type_id<void>();

View File

@@ -9,6 +9,7 @@
# include <boost/python/detail/referent_storage.hpp> # include <boost/python/detail/referent_storage.hpp>
# include <boost/python/detail/destroy.hpp> # include <boost/python/detail/destroy.hpp>
# include <boost/python/detail/type_traits.hpp> # include <boost/python/detail/type_traits.hpp>
# include <boost/align/align.hpp>
# include <boost/static_assert.hpp> # include <boost/static_assert.hpp>
# include <cstddef> # include <cstddef>
@@ -132,7 +133,13 @@ template <class T>
inline rvalue_from_python_data<T>::~rvalue_from_python_data() inline rvalue_from_python_data<T>::~rvalue_from_python_data()
{ {
if (this->stage1.convertible == this->storage.bytes) if (this->stage1.convertible == this->storage.bytes)
python::detail::destroy_referent<ref_type>(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<T>::value, 0, ptr, allocated);
python::detail::destroy_referent<ref_type>(aligned_storage);
}
} }
}}} // namespace boost::python::converter }}} // namespace boost::python::converter

View File

@@ -49,13 +49,17 @@ struct shared_ptr_from_python
new (storage) SP<T>(); new (storage) SP<T>();
else else
{ {
SP<void> hold_convertible_ref_count( void *const storage = ((converter::rvalue_from_python_storage<SP<T> >*)data)->storage.bytes;
(void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); // Deal with the "None" case.
// use aliasing constructor if (data->convertible == source)
new (storage) SP<T>(hold_convertible_ref_count, new (storage) SP<T>();
static_cast<T*>(data->convertible)); else
{
SP<void> hold_convertible_ref_count((void*)0, shared_ptr_deleter(handle<>(borrowed(source))) );
// use aliasing constructor
new (storage) SP<T>(hold_convertible_ref_count, static_cast<T*>(data->convertible));
}
} }
data->convertible = storage; data->convertible = storage;
} }
}; };

View File

@@ -57,9 +57,15 @@
****************************************************************************/ ****************************************************************************/
// backwards compatibility: // backwards compatibility:
#ifdef BOOST_PYTHON_STATIC_LIB #if defined(BOOST_PYTHON_STATIC_LINK) && !defined(BOOST_PYTHON_STATIC_LIB)
# define BOOST_PYTHON_STATIC_LINK # define BOOST_PYTHON_STATIC_LIB
# elif !defined(BOOST_PYTHON_DYNAMIC_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 # define BOOST_PYTHON_DYNAMIC_LIB
#endif #endif

View File

@@ -5,39 +5,21 @@
#ifndef REFERENT_STORAGE_DWA200278_HPP #ifndef REFERENT_STORAGE_DWA200278_HPP
# define REFERENT_STORAGE_DWA200278_HPP # define REFERENT_STORAGE_DWA200278_HPP
# include <boost/mpl/if.hpp> # include <boost/mpl/if.hpp>
# include <boost/type_traits/aligned_storage.hpp>
# include <cstddef> # include <cstddef>
namespace boost { namespace python { namespace detail { namespace boost { namespace python { namespace detail {
struct alignment_dummy; template <std::size_t size, std::size_t alignment = std::size_t(-1)>
typedef void (*function_ptr)(); struct aligned_storage
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 <std::size_t size>
union aligned_storage
{ {
BOOST_PYTHON_ALIGNER(char, 0); union type
BOOST_PYTHON_ALIGNER(short, 1); {
BOOST_PYTHON_ALIGNER(int, 2); typename ::boost::aligned_storage<size, alignment>::type data;
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);
char bytes[size]; char bytes[size];
};
}; };
# undef BOOST_PYTHON_ALIGNER
// Compute the size of T's referent. We wouldn't need this at all, // Compute the size of T's referent. We wouldn't need this at all,
// but sizeof() is broken in CodeWarriors <= 8.0 // but sizeof() is broken in CodeWarriors <= 8.0
template <class T> struct referent_size; template <class T> struct referent_size;
@@ -50,15 +32,12 @@ union aligned_storage
std::size_t, value = sizeof(T)); std::size_t, value = sizeof(T));
}; };
// A metafunction returning a POD type which can store U, where 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. // U&. If T is not a reference type, returns a POD which can store T.
template <class T> template <class T>
struct referent_storage struct referent_storage
{ {
typedef aligned_storage< typedef typename aligned_storage<referent_size<T>::value, alignment_of<T>::value>::type type;
::boost::python::detail::referent_size<T>::value
> type;
}; };
}}} // namespace boost::python::detail }}} // namespace boost::python::detail

View File

@@ -7,7 +7,7 @@
# include <boost/python/detail/prefix.hpp> # include <boost/python/detail/prefix.hpp>
# include <boost/bind.hpp> # include <boost/bind/bind.hpp>
# include <boost/bind/placeholders.hpp> # include <boost/bind/placeholders.hpp>
# include <boost/type.hpp> # include <boost/type.hpp>
# include <boost/python/detail/translate_exception.hpp> # include <boost/python/detail/translate_exception.hpp>
@@ -18,6 +18,7 @@ namespace boost { namespace python {
template <class ExceptionType, class Translate> template <class ExceptionType, class Translate>
void register_exception_translator(Translate translate, boost::type<ExceptionType>* = 0) void register_exception_translator(Translate translate, boost::type<ExceptionType>* = 0)
{ {
using namespace boost::placeholders;
detail::register_exception_handler( detail::register_exception_handler(
boost::bind<bool>(detail::translate_exception<ExceptionType,Translate>(), _1, _2, translate) boost::bind<bool>(detail::translate_exception<ExceptionType,Translate>(), _1, _2, translate)
); );

View File

@@ -38,7 +38,7 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable
// Allocate storage for an object of the given size at the given // Allocate storage for an object of the given size at the given
// offset in the Python instance<> object if bytes are available // offset in the Python instance<> object if bytes are available
// there. Otherwise allocate size bytes of heap memory. // 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 // Deallocate storage from the heap if it was not carved out of
// the given Python object by allocate(), above. // the given Python object by allocate(), above.

View File

@@ -22,7 +22,7 @@ works correctly. */
# pragma warning(disable: 4180) # pragma warning(disable: 4180)
# endif # endif
# include <boost/bind.hpp> # include <boost/bind/bind.hpp>
# include <boost/bind/protect.hpp> # include <boost/bind/protect.hpp>
namespace boost { namespace python { namespace boost { namespace python {
@@ -40,6 +40,7 @@ namespace detail
, Target&(*)() , Target&(*)()
) )
{ {
using namespace boost::placeholders;
return objects::make_iterator_function<Target>( return objects::make_iterator_function<Target>(
boost::protect(boost::bind(get_start, _1)) boost::protect(boost::bind(get_start, _1))
, boost::protect(boost::bind(get_finish, _1)) , boost::protect(boost::bind(get_finish, _1))

View File

@@ -61,7 +61,8 @@ namespace detail
typedef objects::pointer_holder<Ptr,value_type> holder; typedef objects::pointer_holder<Ptr,value_type> holder;
typedef objects::instance<holder> instance_t; typedef objects::instance<holder> 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<holder>::value);
try { try {
#if defined(BOOST_NO_CXX11_SMART_PTR) #if defined(BOOST_NO_CXX11_SMART_PTR)
(new (memory) holder(x))->install(this->m_self); (new (memory) holder(x))->install(this->m_self);

View File

@@ -18,6 +18,8 @@ BOOST_PYTHON_DECL void add_to_namespace(
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); 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 }}} // namespace boost::python::objects
#endif // ADD_TO_NAMESPACE_DWA200286_HPP #endif // ADD_TO_NAMESPACE_DWA200286_HPP

View File

@@ -35,6 +35,8 @@ struct BOOST_PYTHON_DECL function : PyObject
static void add_to_namespace( static void add_to_namespace(
object const& name_space, char const* name, object const& attribute, char const* doc); 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; object const& doc() const;
void doc(object const& x); void doc(object const& x);
@@ -42,6 +44,8 @@ struct BOOST_PYTHON_DECL function : PyObject
object const& get_namespace() const { return m_namespace; } object const& get_namespace() const { return m_namespace; }
object const& get_module() const { return m_module; }
private: // helper functions private: // helper functions
object signature(bool show_return_type=false) const; object signature(bool show_return_type=false) const;
object signatures(bool show_return_type=false) const; object signatures(bool show_return_type=false) const;
@@ -53,6 +57,7 @@ struct BOOST_PYTHON_DECL function : PyObject
handle<function> m_overloads; handle<function> m_overloads;
object m_name; object m_name;
object m_namespace; object m_namespace;
object m_module;
object m_doc; object m_doc;
object m_arg_names; object m_arg_names;
unsigned m_nkeyword_values; unsigned m_nkeyword_values;

View File

@@ -18,13 +18,13 @@
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {
class function_doc_signature_generator{ 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, const object& current_module_name);
static bool arity_cmp( function const *f1, function const *f2 ); 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 bool are_seq_overloads( function const *f1, function const *f2 , bool check_docs);
static std::vector<function const*> flatten(function const *f); static std::vector<function const*> flatten(function const *f);
static std::vector<function const*> split_seq_overloads( const std::vector<function const *> &funcs, bool split_on_doc_change); static std::vector<function const*> split_seq_overloads( const std::vector<function const *> &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 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); static str pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false);
public: public:

View File

@@ -6,7 +6,7 @@
# define INSTANCE_DWA200295_HPP # define INSTANCE_DWA200295_HPP
# include <boost/python/detail/prefix.hpp> # include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <cstddef> # include <cstddef>
namespace boost { namespace python namespace boost { namespace python
@@ -28,7 +28,7 @@ struct instance
typedef typename boost::python::detail::type_with_alignment< typedef typename boost::python::detail::type_with_alignment<
boost::python::detail::alignment_of<Data>::value boost::python::detail::alignment_of<Data>::value
>::type align_t; >::type align_t;
union union
{ {
align_t align; align_t align;
@@ -41,9 +41,10 @@ struct additional_instance_size
{ {
typedef instance<Data> instance_data; typedef instance<Data> instance_data;
typedef instance<char> instance_char; typedef instance<char> instance_char;
BOOST_STATIC_CONSTANT( BOOST_STATIC_CONSTANT(std::size_t,
std::size_t, value = sizeof(instance_data) value = sizeof(instance_data) -
- BOOST_PYTHON_OFFSETOF(instance_char,storage)); BOOST_PYTHON_OFFSETOF(instance_char,storage) +
boost::python::detail::alignment_of<Data>::value);
}; };
}}} // namespace boost::python::object }}} // namespace boost::python::object

View File

@@ -89,8 +89,9 @@ struct make_holder<N>
BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a)) BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a))
{ {
typedef instance<Holder> instance_t; typedef instance<Holder> 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<Holder>::value);
try { try {
(new (memory) Holder( (new (memory) Holder(
p BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); p BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p);

View File

@@ -43,11 +43,14 @@ struct make_instance_impl
// construct the new C++ object and install the pointer // construct the new C++ object and install the pointer
// in the Python object. // 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, // Note the position of the internally-stored Holder,
// for the sake of destruction // for the sake of destruction
Py_SET_SIZE(instance, offsetof(instance_t, storage)); const size_t offset = reinterpret_cast<size_t>(holder) -
reinterpret_cast<size_t>(instance->storage.bytes) + offsetof(instance_t, storage);
Py_SET_SIZE(instance, offset);
// Release ownership of the python object // Release ownership of the python object
protect.cancel(); protect.cancel();
@@ -69,7 +72,10 @@ struct make_instance
static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper<T const> x) static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper<T const> x)
{ {
return new (storage) Holder(instance, x); size_t allocated = objects::additional_instance_size<Holder>::value;
void* aligned_storage = ::boost::alignment::align(boost::python::detail::alignment_of<Holder>::value,
sizeof(Holder), storage, allocated);
return new (aligned_storage) Holder(instance, x);
} }
}; };

View File

@@ -9,7 +9,7 @@
# include <boost/python/object_core.hpp> # include <boost/python/object_core.hpp>
# include <boost/python/call.hpp> # include <boost/python/call.hpp>
# include <boost/iterator/detail/enable_if.hpp> # include <boost/type_traits/enable_if.hpp>
# include <boost/mpl/bool.hpp> # include <boost/mpl/bool.hpp>
# include <boost/iterator/detail/config_def.hpp> # include <boost/iterator/detail/config_def.hpp>
@@ -40,7 +40,7 @@ struct is_object_operators
# if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) # if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE)
template <class L, class R, class T> template <class L, class R, class T>
struct enable_binary struct enable_binary
: boost::iterators::enable_if<is_object_operators<L,R>, T> : boost::enable_if_<is_object_operators<L,R>::value, T>
{}; {};
# define BOOST_PYTHON_BINARY_RETURN(T) typename enable_binary<L,R,T>::type # define BOOST_PYTHON_BINARY_RETURN(T) typename enable_binary<L,R,T>::type
# else # else

View File

@@ -96,6 +96,7 @@ namespace detail
, make_function( , make_function(
detail::nullary_function_adaptor<void(*)()>(pure_virtual_called) detail::nullary_function_adaptor<void(*)()>(pure_virtual_called)
, default_call_policies() , default_call_policies()
, options.keywords()
, detail::error_signature<held_type>(detail::get_signature(m_pmf)) , detail::error_signature<held_type>(detail::get_signature(m_pmf))
) )
); );

View File

@@ -222,7 +222,13 @@ namespace
, char const* ref_type) , char const* ref_type)
{ {
handle<> holder(source); handle<> holder(source);
if (source->ob_refcnt <= 1) if (
#if PY_VERSION_HEX < 0x03090000
source->ob_refcnt
#else
Py_REFCNT(source)
#endif
<= 1)
{ {
handle<> msg( handle<> msg(
#if PY_VERSION_HEX >= 0x3000000 #if PY_VERSION_HEX >= 0x3000000

View File

@@ -109,8 +109,8 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l
PyObject *fo = Py_BuildValue("s", f); PyObject *fo = Py_BuildValue("s", f);
PyObject *fb = Py_None; PyObject *fb = Py_None;
PyUnicode_FSConverter(fo, &fb); PyUnicode_FSConverter(fo, &fb);
f = PyBytes_AsString(fb); char *f_as_uft = PyBytes_AsString(fb);
FILE *fs = fopen(f, "r"); FILE *fs = fopen(f_as_uft, "r");
Py_DECREF(fo); Py_DECREF(fo);
Py_DECREF(fb); Py_DECREF(fb);
#elif PY_VERSION_HEX >= 0x03000000 #elif PY_VERSION_HEX >= 0x03000000
@@ -129,6 +129,7 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l
f, f,
Py_file_input, Py_file_input,
global.ptr(), local.ptr()); global.ptr(), local.ptr());
fclose(fs);
if (!result) throw_error_already_set(); if (!result) throw_error_already_set();
return object(detail::new_reference(result)); return object(detail::new_reference(result));
} }

View File

@@ -98,35 +98,16 @@ python::detail::new_reference dtype::convert(object const & arg, bool align)
return python::detail::new_reference(reinterpret_cast<PyObject*>(obj)); return python::detail::new_reference(reinterpret_cast<PyObject*>(obj));
} }
int dtype::get_itemsize() const { return reinterpret_cast<PyArray_Descr*>(ptr())->elsize;} int dtype::get_itemsize() const {
#if NPY_ABI_VERSION < 0x02000000
return reinterpret_cast<PyArray_Descr*>(ptr())->elsize;
#else
return PyDataType_ELSIZE(reinterpret_cast<PyArray_Descr*>(ptr()));
#endif
}
bool equivalent(dtype const & a, dtype const & b) { bool equivalent(dtype const & a, dtype const & b) {
// On Windows x64, the behaviour described on return a == b;
// 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<long>() || a == dtype::get_builtin<int>()) &&
(b == dtype::get_builtin<long>() || b == dtype::get_builtin<int>()) ||
(a == dtype::get_builtin<unsigned int>() || a == dtype::get_builtin<unsigned long>()) &&
(b == dtype::get_builtin<unsigned int>() || b == dtype::get_builtin<unsigned long>()))) {
return true;
} else {
return PyArray_EquivTypes(
reinterpret_cast<PyArray_Descr*>(a.ptr()),
reinterpret_cast<PyArray_Descr*>(b.ptr())
);
}
#else
return PyArray_EquivTypes(
reinterpret_cast<PyArray_Descr*>(a.ptr()),
reinterpret_cast<PyArray_Descr*>(b.ptr())
);
#endif
} }
namespace namespace

View File

@@ -5,6 +5,7 @@
#include <boost/python/detail/prefix.hpp> #include <boost/python/detail/prefix.hpp>
#include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround #include <boost/mpl/lambda.hpp> // #including this first is an intel6 workaround
#include <boost/cstdint.hpp>
#include <boost/python/object/class.hpp> #include <boost/python/object/class.hpp>
#include <boost/python/object/instance.hpp> #include <boost/python/object/instance.hpp>
@@ -332,8 +333,9 @@ namespace objects
for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) for (instance_holder* p = kill_me->objects, *next; p != 0; p = next)
{ {
next = p->next(); next = p->next();
void* q = dynamic_cast<void*>(p);
p->~instance_holder(); p->~instance_holder();
instance_holder::deallocate(inst, dynamic_cast<void*>(p)); instance_holder::deallocate(inst, q);
} }
// Python 2.2.1 won't add weak references automatically when // Python 2.2.1 won't add weak references automatically when
@@ -501,6 +503,16 @@ namespace objects
); );
} }
object 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 namespace
{ {
// Find a registered class object corresponding to id. Return a // Find a registered class object corresponding to id. Return a
@@ -563,6 +575,9 @@ namespace objects
object m = module_prefix(); object m = module_prefix();
if (m) d["__module__"] = m; if (m) d["__module__"] = m;
#if PY_VERSION_HEX >= 0x03030000
d["__qualname__"] = qualname(name);
#endif
if (doc != 0) if (doc != 0)
d["__doc__"] = doc; d["__doc__"] = doc;
@@ -721,28 +736,46 @@ namespace objects
} // 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)); assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object));
objects::instance<>* self = (objects::instance<>*)self_; 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) if (-Py_SIZE(self) >= total_size_needed)
{ {
// holder_offset should at least point into the variable-sized part // holder_offset should at least point into the variable-sized part
assert(holder_offset >= offsetof(objects::instance<>,storage)); 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 // Record the fact that the storage is occupied, noting where it starts
Py_SET_SIZE(self, holder_offset); const size_t offset = reinterpret_cast<uintptr_t>(aligned_storage) - reinterpret_cast<uintptr_t>(storage) + holder_offset;
return (char*)self + holder_offset; Py_SET_SIZE(self, offset);
return (char*)self + offset;
} }
else else
{ {
void* const result = PyMem_Malloc(holder_size); const size_t base_allocation = sizeof(alignment_marker_t) + holder_size + alignment - 1;
if (result == 0) void* const base_storage = PyMem_Malloc(base_allocation);
if (base_storage == 0)
throw std::bad_alloc(); throw std::bad_alloc();
return result;
const uintptr_t x = reinterpret_cast<uintptr_t>(base_storage) + sizeof(alignment_marker_t);
// 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);
alignment_marker_t* const marker_storage = reinterpret_cast<alignment_marker_t *>((char *)aligned_storage - sizeof(alignment_marker_t));
*marker_storage = static_cast<alignment_marker_t>(padding);
return aligned_storage;
} }
} }
@@ -752,7 +785,9 @@ void instance_holder::deallocate(PyObject* self_, void* storage) throw()
objects::instance<>* self = (objects::instance<>*)self_; objects::instance<>* self = (objects::instance<>*)self_;
if (storage != (char*)self + Py_SIZE(self)) if (storage != (char*)self + Py_SIZE(self))
{ {
PyMem_Free(storage); alignment_marker_t* marker_storage = reinterpret_cast<alignment_marker_t *>((char *)storage - sizeof(alignment_marker_t));
void *malloced_storage = (char *) storage - sizeof(alignment_marker_t) - (*marker_storage);
PyMem_Free(malloced_storage);
} }
} }

View File

@@ -49,7 +49,9 @@ extern "C"
if (!self->name) if (!self->name)
{ {
return 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_)); PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_));
#else #else
PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_)); 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 0;
return 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); PyUnicode_FromFormat("%S.%s.%S", mod, self_->ob_type->tp_name, name);
#else #else
PyString_FromFormat("%s.%s.%s", PyString_FromFormat("%s.%s.%s",
@@ -113,7 +117,6 @@ static PyTypeObject enum_type_object = {
#if PY_VERSION_HEX < 0x03000000 #if PY_VERSION_HEX < 0x03000000
| Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_CHECKTYPES
#endif #endif
| Py_TPFLAGS_HAVE_GC
| Py_TPFLAGS_BASETYPE, /* tp_flags */ | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
0, /* tp_traverse */ 0, /* tp_traverse */
@@ -146,6 +149,7 @@ static PyTypeObject enum_type_object = {
}; };
object module_prefix(); object module_prefix();
object qualname(const char *name);
namespace namespace
{ {
@@ -176,6 +180,11 @@ namespace
object module_name = module_prefix(); object module_name = module_prefix();
if (module_name) if (module_name)
d["__module__"] = module_name; d["__module__"] = module_name;
#if PY_VERSION_HEX >= 0x03030000
object q = qualname(name);
if (q)
d["__qualname__"] = q;
#endif
if (doc) if (doc)
d["__doc__"] = doc; d["__doc__"] = doc;

View File

@@ -21,7 +21,7 @@
#include <boost/python/detail/none.hpp> #include <boost/python/detail/none.hpp>
#include <boost/mpl/vector/vector10.hpp> #include <boost/mpl/vector/vector10.hpp>
#include <boost/bind.hpp> #include <boost/bind/bind.hpp>
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
@@ -419,6 +419,30 @@ namespace detail
extern char cpp_signature_tag[]; 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<const char*>(detail::py_signature_tag));
}
if (doc != 0 && docstring_options::show_user_defined_)
_doc += doc;
if (docstring_options::show_cpp_signatures_)
{
_doc += str(const_cast<const char*>(detail::cpp_signature_tag));
}
if(_doc)
{
object mutable_attribute(attribute);
mutable_attribute.attr("__doc__")= _doc;
}
return attribute;
}
void function::add_to_namespace( void function::add_to_namespace(
object const& name_space, char const* name_, object const& attribute, char const* doc) object const& name_space, char const* name_, object const& attribute, char const* doc)
{ {
@@ -489,11 +513,24 @@ void function::add_to_namespace(
assert(!PyErr_Occurred()); assert(!PyErr_Occurred());
handle<> name_space_name( handle<> name_space_name(
allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast<char*>("__name__")))); allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast<char*>(
#if PY_VERSION_HEX < 0x03030000
"__name__"
#else
"__qualname__"
#endif
))));
PyErr_Clear(); PyErr_Clear();
if (name_space_name) if (name_space_name)
new_func->m_namespace = object(name_space_name); new_func->m_namespace = object(name_space_name);
object module_name(
PyObject_IsInstance(name_space.ptr(), upcast<PyObject>(&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) if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0)
@@ -532,24 +569,7 @@ void function::add_to_namespace(
"C++ signature:", f->signature(true))); "C++ signature:", f->signature(true)));
} }
*/ */
str _doc; add_doc(attribute, doc);
if (docstring_options::show_py_signatures_)
{
_doc += str(const_cast<const char*>(detail::py_signature_tag));
}
if (doc != 0 && docstring_options::show_user_defined_)
_doc += doc;
if (docstring_options::show_cpp_signatures_)
{
_doc += str(const_cast<const char*>(detail::cpp_signature_tag));
}
if(_doc)
{
object mutable_attribute(attribute);
mutable_attribute.attr("__doc__")= _doc;
}
} }
BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL void add_to_namespace(
@@ -564,6 +584,18 @@ BOOST_PYTHON_DECL void add_to_namespace(
function::add_to_namespace(name_space, name, attribute, doc); function::add_to_namespace(name_space, name, attribute, doc);
} }
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);
}
namespace namespace
{ {
@@ -670,7 +702,7 @@ extern "C"
static PyObject* function_get_module(PyObject* op, void*) static PyObject* function_get_module(PyObject* op, void*)
{ {
function* f = downcast<function>(op); function* f = downcast<function>(op);
object const& ns = f->get_namespace(); object const& ns = f->get_module();
if (!ns.is_none()) { if (!ns.is_none()) {
return python::incref(ns.ptr()); return python::incref(ns.ptr());
} }

View File

@@ -114,23 +114,47 @@ namespace boost { namespace python { namespace objects {
return res; return res;
} }
const char * 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 &current_module_name)
{ {
if (s.basename==std::string("void")){ if (s.basename==std::string("void")){
static const char * none = "None"; static const char * none = "None";
return none; return str(none);
} }
PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0; PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0;
if ( py_type ) if ( py_type ) {
return py_type->tp_name; str name(get_qualname(py_type));
else{ 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"; static const char * object = "object";
return 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; str param;
@@ -156,12 +180,12 @@ namespace boost { namespace python { namespace objects {
{ {
object kv; object kv;
if ( arg_names && (kv = arg_names[n-1]) ) 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 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 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 //an argument - check for default value and append it
@@ -199,7 +223,7 @@ namespace boost { namespace python { namespace objects {
str param; str param;
formal_params.append( 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 // find all the arguments with default values preceeding the arity-n_overloads

View File

@@ -11,7 +11,7 @@
#include <boost/graph/adjacency_list.hpp> #include <boost/graph/adjacency_list.hpp>
#include <boost/graph/reverse_graph.hpp> #include <boost/graph/reverse_graph.hpp>
#include <boost/property_map/property_map.hpp> #include <boost/property_map/property_map.hpp>
#include <boost/bind.hpp> #include <boost/bind/bind.hpp>
#include <boost/integer_traits.hpp> #include <boost/integer_traits.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/tuple/tuple_comparison.hpp> #include <boost/tuple/tuple_comparison.hpp>
@@ -184,6 +184,7 @@ namespace
// map a type to a position in the index // map a type to a position in the index
inline type_index_t::iterator type_position(class_id type) inline type_index_t::iterator type_position(class_id type)
{ {
using namespace boost::placeholders;
typedef index_entry entry; typedef index_entry entry;
return std::lower_bound( return std::lower_bound(

View File

@@ -5,7 +5,7 @@
#include <boost/python/object/iterator_core.hpp> #include <boost/python/object/iterator_core.hpp>
#include <boost/python/object/function_object.hpp> #include <boost/python/object/function_object.hpp>
#include <boost/bind.hpp> #include <boost/bind/bind.hpp>
#include <boost/mpl/vector/vector10.hpp> #include <boost/mpl/vector/vector10.hpp>
namespace boost { namespace python { namespace objects { namespace boost { namespace python { namespace objects {

View File

@@ -34,4 +34,14 @@ slice_base::step() const
((PySliceObject*)this->ptr())->step)); ((PySliceObject*)this->ptr())->step));
} }
static struct register_slice_pytype_ptr
{
register_slice_pytype_ptr()
{
const_cast<converter::registration &>(
converter::registry::lookup(boost::python::type_id<boost::python::slice>())
).m_class_object = &PySlice_Type;
}
}register_slice_pytype_ptr_;
} } } // !namespace boost::python::detail } } } // !namespace boost::python::detail

View File

@@ -2,14 +2,16 @@
# Software License, Version 1.0. (See accompanying # Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) # 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 python ;
import os ; import os ;
import ../../config/checks/config : requires ; import config : requires ;
lib socket ; lib socket ;
use-project /boost/python : ../build ; project
project /boost/python/test
: requirements : requirements
<toolset>gcc:<cxxflags>-Wextra <toolset>gcc:<cxxflags>-Wextra
<target-os>qnxnto:<library>socket <target-os>qnxnto:<library>socket
@@ -28,7 +30,7 @@ rule py-run ( sources * : input-file ? )
: $(input-file) : $(input-file)
: #requirements : #requirements
<define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION <define>BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION
] ; ] ;
} }
@@ -52,6 +54,18 @@ rule require-windows ( properties * )
if [ python.configured ] if [ python.configured ]
{ {
alias base_deps : usage-requirements
<library>/boost/align//boost_align
<library>/boost/assert//boost_assert
<library>/boost/config//boost_config
<library>/boost/core//boost_core
<library>/boost/detail//boost_detail
<library>/boost/function//boost_function
<library>/boost/mpl//boost_mpl
<library>/boost/preprocessor//boost_preprocessor
<library>/boost/static_assert//boost_static_assert
<library>/boost/type_traits//boost_type_traits
;
test-suite python test-suite python
: :
@@ -97,8 +111,8 @@ bpl-test crossmod_exception
[ bpl-test andreas_beyer ] [ bpl-test andreas_beyer ]
[ bpl-test wrapper_held_type ] [ bpl-test wrapper_held_type ]
[ bpl-test polymorphism2_auto_ptr [ bpl-test polymorphism2_auto_ptr
: polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp
: [ requires auto_ptr ] : [ requires auto_ptr ]
] ]
@@ -119,7 +133,7 @@ bpl-test crossmod_exception
[ bpl-test try : newtest.py m1.cpp m2.cpp ] [ bpl-test try : newtest.py m1.cpp m2.cpp ]
[ bpl-test const_argument ] [ bpl-test const_argument ]
[ bpl-test keywords : keywords.cpp keywords_test.py ] [ bpl-test keywords : keywords.cpp keywords_test.py ]
[ python-extension builtin_converters_ext : builtin_converters.cpp /boost/python//boost_python ] [ python-extension builtin_converters_ext : builtin_converters.cpp /boost/python//boost_python ]
[ bpl-test builtin_converters : test_builtin_converters.py builtin_converters_ext ] [ bpl-test builtin_converters : test_builtin_converters.py builtin_converters_ext ]
@@ -132,6 +146,7 @@ bpl-test crossmod_exception
[ bpl-test object ] [ bpl-test object ]
[ bpl-test class ] [ bpl-test class ]
[ bpl-test aligned_class ]
[ bpl-test list ] [ bpl-test list ]
[ bpl-test long ] [ bpl-test long ]
[ bpl-test dict ] [ bpl-test dict ]
@@ -191,13 +206,13 @@ bpl-test crossmod_opaque
# Whenever the cause for the failure of the polymorphism test is found # Whenever the cause for the failure of the polymorphism test is found
# and fixed, this should be retested. # and fixed, this should be retested.
<toolset>hp_cxx:<build>no ] <toolset>hp_cxx:<build>no ]
[ python-extension map_indexing_suite_ext [ python-extension map_indexing_suite_ext
: map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp : map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp
/boost/python//boost_python ] /boost/python//boost_python ]
[ bpl-test [ bpl-test
map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ] map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ]
[ run import_.cpp /boost/python//boost_python $(PY) : : import_.py ] [ run import_.cpp /boost/python//boost_python $(PY) : : import_.py ]
# if $(TEST_BIENSTMAN_NON_BUGS) # if $(TEST_BIENSTMAN_NON_BUGS)
@@ -211,28 +226,29 @@ bpl-test crossmod_opaque
# --- unit tests of library components --- # --- unit tests of library components ---
[ compile indirect_traits_test.cpp ] [ compile indirect_traits_test.cpp : <use>base_deps ]
[ run destroy_test.cpp ] [ run destroy_test.cpp : : : <use>base_deps ]
[ py-run pointer_type_id_test.cpp ] [ py-run pointer_type_id_test.cpp ]
[ py-run bases.cpp ] [ py-run bases.cpp ]
[ run if_else.cpp ] [ run if_else.cpp : : : <use>base_deps ]
[ py-run pointee.cpp ] [ py-run pointee.cpp ]
[ run result.cpp ] [ run result.cpp : : : <use>base_deps ]
[ compile string_literal.cpp ] [ compile string_literal.cpp : <use>base_deps ]
[ py-compile borrowed.cpp ] [ py-compile borrowed.cpp ]
[ py-compile object_manager.cpp ] [ py-compile object_manager.cpp ]
[ py-compile copy_ctor_mutates_rhs.cpp ] [ py-compile copy_ctor_mutates_rhs.cpp ]
[ py-run upcast.cpp ] [ py-run upcast.cpp ]
[ py-compile select_holder.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
: :
: :
: <define>BOOST_PYTHON_STATIC_LIB : <define>BOOST_PYTHON_STATIC_LIB
<use>$(PY) <use>$(PY)
<use>base_deps
] ]

33
test/aligned_class.cpp Normal file
View File

@@ -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 <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/object.hpp>
#include <boost/python/class.hpp>
#include <boost/assert.hpp>
#include <boost/cstdint.hpp>
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<uintptr_t>(&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>("X", init<int, float>());
def("x_function", x_function);
def("f_function", f_function);
}
#include "module_tail.cpp"

44
test/aligned_class.py Executable file
View File

@@ -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)

View File

@@ -79,6 +79,8 @@ for t in [('injected',),
('callbacks',), ('callbacks',),
('defaults',), ('defaults',),
('object',), ('object',),
('class',),
('aligned_class',),
('list',), ('list',),
('long',), ('long',),
('dict',), ('dict',),

View File

@@ -6,7 +6,7 @@
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/detail/lightweight_test.hpp> #include <boost/detail/lightweight_test.hpp>
#include <boost/bind.hpp> #include <boost/bind/bind.hpp>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>

View File

@@ -214,6 +214,13 @@ joel kimpo
... i.data() ... i.data()
4 4
#####################################################################
# Test signature...
#####################################################################
>>> AMap.__iter__.__doc__.strip().split("\\n")[0]
'__iter__( (AMap)arg1) -> __main__.iterator :'
##################################################################### #####################################################################
# END.... # END....
##################################################################### #####################################################################

View File

@@ -4,6 +4,8 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/module.hpp> #include <boost/python/module.hpp>
#include <boost/python/class.hpp> #include <boost/python/class.hpp>
#include <boost/python/def.hpp>
#include <boost/python/enum.hpp>
#include <boost/python/operators.hpp> #include <boost/python/operators.hpp>
#include <boost/python/scope.hpp> #include <boost/python/scope.hpp>
#include "test_class.hpp" #include "test_class.hpp"
@@ -16,6 +18,8 @@
typedef test_class<> X; typedef test_class<> X;
typedef test_class<1> Y; typedef test_class<1> Y;
enum color { red = 0, blue = 1, green = 2 };
std::ostream& operator<<(std::ostream& s, X const& x) std::ostream& operator<<(std::ostream& s, X const& x)
{ {
return s << x.value(); return s << x.value();
@@ -26,11 +30,13 @@ std::ostream& operator<<(std::ostream& s, Y const& x)
return s << x.value(); return s << x.value();
} }
void test_function(const X& x, const Y& y) {}
BOOST_PYTHON_MODULE(nested_ext) BOOST_PYTHON_MODULE(nested_ext)
{ {
using namespace boost::python; using namespace boost::python;
{
// Establish X as the current scope. // Establish X as the current scope.
scope x_class scope x_class
= class_<X>("X", init<int>()) = class_<X>("X", init<int>())
@@ -42,6 +48,17 @@ BOOST_PYTHON_MODULE(nested_ext)
class_<Y>("Y", init<int>()) class_<Y>("Y", init<int>())
.def(str(self)) .def(str(self))
; ;
// so will the enum `color`
enum_<color>("color")
.value("red", red)
.value("green", green)
.value("blue", blue)
;
}
// The generated docstring will use the fully-qualified name of Y
def("test_function", &test_function);
} }

View File

@@ -13,14 +13,35 @@
>>> X.__name__ >>> X.__name__
'X' 'X'
>>> X.Y >>> X.Y # doctest: +py2
<class 'nested_ext.Y'> <class 'nested_ext.Y'>
>>> X.Y # doctest: +py3
<class 'nested_ext.X.Y'>
>>> X.Y.__module__ >>> X.Y.__module__
'nested_ext' 'nested_ext'
>>> X.Y.__name__ >>> X.Y.__name__
'Y' 'Y'
>>> getattr(X.color, "__qualname__", None) # doctest: +py3
'X.color'
>>> 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)) # doctest: +py2
'nested_ext.color(1)'
>>> repr(X.color(1)) # doctest: +py3
'nested_ext.X.color(1)'
>>> test_function.__doc__.strip().split('\\n')[0] # doctest: +py3
'test_function( (X)arg1, (X.Y)arg2) -> None :'
''' '''
@@ -30,7 +51,23 @@ def run(args = None):
if args is not None: if args is not None:
sys.argv = args 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__': if __name__ == '__main__':
print("running...") print("running...")

View File

@@ -64,6 +64,7 @@ BOOST_PYTHON_MODULE(properties_ext)
class_<X>("X", init<int>() ) class_<X>("X", init<int>() )
//defining read only property //defining read only property
.add_property( "value_r", &X::get_value ) .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") .add_property( "value_r_ds", &X::get_value, "value_r_ds is read-only")
//defining read \ write property //defining read \ write property
.add_property( "value_rw", &X::get_value, &X::set_value ) .add_property( "value_rw", &X::get_value, &X::set_value )

View File

@@ -20,6 +20,9 @@ value read only
>>> x1.value_r >>> x1.value_r
1 1
>>> x1.value_r_f
1
value read - write value read - write
>>> x1.value_rw >>> x1.value_rw
1 1
@@ -84,8 +87,27 @@ after creating second intstance of X instances count is 2
>>> assert properties.X.value_rw_ds.__doc__ == "value_rw_ds is read-write" >>> 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 sys; sys.path.append(r'P:\Actimize4.0\smart_const\py_smart_const___Win32_Debug')
import properties_ext as properties import properties_ext as properties

View File

@@ -33,6 +33,8 @@ test passed
0 0
>>> check_slice_get_indices( slice( -2, -5, -2)) >>> check_slice_get_indices( slice( -2, -5, -2))
6 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. # Performs an affirmative and negative argument resolution check.