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

Compare commits

..

1 Commits

Author SHA1 Message Date
Peter Dimov
f09045ae62 Normalize static/dynamic link macros and avoid redefinition warnings 2023-12-22 05:36:47 +02:00
74 changed files with 247 additions and 1034 deletions

65
.github/get-py-env.py vendored
View File

@@ -1,65 +0,0 @@
#!/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()

46
.github/run-faber.sh vendored
View File

@@ -1,46 +0,0 @@
#!/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` \
"$@"

View File

@@ -4,14 +4,14 @@ on: [push]
jobs: jobs:
deploy: deploy:
runs-on: ubuntu-24.04 runs-on: ubuntu-20.04
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v2
- name: setup - name: setup
run: | run: |
sudo apt-get update sudo apt-get update
sudo apt-get install \ sudo apt-get install \
libboost-tools-dev \ libboost1.71-tools-dev \
python3 \ python3 \
python3-numpy \ python3-numpy \
python3-sphinx \ python3-sphinx \
@@ -29,7 +29,7 @@ jobs:
echo "destination_dir=doc/develop/html" >> $GITHUB_ENV echo "destination_dir=doc/develop/html" >> $GITHUB_ENV
fi fi
- name: deploy - name: deploy
uses: peaceiris/actions-gh-pages@v4 uses: peaceiris/actions-gh-pages@v3
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: build/doc/html publish_dir: build/doc/html

View File

@@ -9,14 +9,14 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: [3.8.10] python-version: [3.6]
cxx: [clang++] cxx: [clang++]
std: [c++11, c++14] # TODO: c++17 is failing ! std: [c++98, c++11, c++14] # TODO: c++17 is failing !
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v2
- name: setup python - name: setup python
uses: actions/setup-python@v6 uses: actions/setup-python@v2
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: setup prerequisites - name: setup prerequisites
@@ -28,23 +28,18 @@ 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

@@ -1,10 +1,6 @@
# Test on Ubuntu with various compiler and language standard versions.
name: Test Ubuntu name: Test Ubuntu
on: on: [push, pull_request]
push:
pull_request:
workflow_dispatch:
jobs: jobs:
build: build:
@@ -13,82 +9,43 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
python-version: ['3.14'] python: [python, python3]
cxx: [g++, clang++] cxx: [g++, clang++]
std: [c++11, c++14, c++17] std: [c++98, c++11, c++14, c++17]
include: include:
- python-version: '2.7' # Add the appropriate docker image for each compiler.
cxx: g++ # The images from teeks99/boost-python-test already have boost::python
std: c++11 # pre-reqs installed, see:
- python-version: '3.10' # https://github.com/teeks99/boost-python-test-docker
cxx: g++ - cxx: clang++
std: c++17 docker-img: teeks99/boost-python-test:clang-12_1.76.0
- python-version: '3.11' - cxx: g++
cxx: g++ docker-img: teeks99/boost-python-test:gcc-10_1.76.0
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++
std: c++17
container: container:
# Add the appropriate docker image for the compiler. image: ${{ matrix.docker-img }}
# 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: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v2
- name: setup python
if: "${{ matrix.python-version != '2.7' }}" - name: build
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: setup prerequisites
run: | run: |
# Warning: this is not necessarily the same Python version as the one configured above ! ${{ matrix.python }} --version
python3 -m pip install -U faber --break-system-packages
echo "CXX=${{ matrix.cxx }}" >> "$GITHUB_ENV"
echo "CXX_STD=${{ matrix.std }}" >> "$GITHUB_ENV"
- name: build-py2
if: "${{ matrix.python-version == '2.7' }}"
run: |
python --version
${{ matrix.cxx }} --version ${{ matrix.cxx }} --version
faber -v faber -v
sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber
faber \ faber \
--with-boost-include=${BOOST_PY_DEPS} \ --with-boost-include=${BOOST_PY_DEPS} \
--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: build-py3 - name: test
if: "${{ matrix.python-version != '2.7' }}"
run: |
.github/run-faber.sh
- name: test-py2
if: "${{ matrix.python-version == '2.7' }}"
run: | run: |
faber \ faber \
--with-boost-include=${BOOST_PY_DEPS} \ --with-boost-include=${BOOST_PY_DEPS} \
--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
- name: test-py3
if: "${{ matrix.python-version != '2.7' }}"
run: |
.github/run-faber.sh test.report

View File

@@ -11,11 +11,11 @@ jobs:
python-version: [3.7] python-version: [3.7]
steps: steps:
- uses: actions/checkout@v5 - uses: actions/checkout@v2
- uses: actions/setup-python@v6 - uses: actions/setup-python@v2
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- uses: microsoft/setup-msbuild@v2 - 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:
@@ -42,8 +42,8 @@ jobs:
- name: build - name: build
shell: cmd shell: cmd
run: | run: |
faber --builddir=build cxx.name=msvc --log=commands --log=output --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 - name: test
shell: cmd shell: cmd
run: | 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

View File

@@ -1,41 +0,0 @@
# 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,34 +30,14 @@ else
; ;
} }
constant boost_dependencies_private : project boost/python
/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
@@ -112,9 +92,8 @@ 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>@tag <tag>@python-tag
<conditional>@python.require-py <conditional>@python.require-py
: # default build : # default build
@@ -122,20 +101,8 @@ 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
@@ -153,9 +120,8 @@ lib boost_numpy
<library>/python//numpy <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>@tag <tag>@python-tag
<conditional>@python.require-py <conditional>@python.require-py
: # default build : # default build
@@ -163,13 +129,39 @@ 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
{ {
alias boost_numpy : config-warning ; # 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 ;
} }

View File

@@ -714,23 +714,3 @@ 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,9 +49,6 @@
{%- 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 %}"
@@ -90,7 +87,7 @@
<tr> <tr>
<td valign="top" width="300"> <td valign="top" width="300">
<h3><a href="{{ pathto('index') }}"><img <h3><a href="{{ pathto('index') }}"><img
alt="C++ Boost" src="{{ pathto('_static/bpl.png', 1) }}" border="0"></a></h3> alt="C++ Boost" src="{{ pathto('_static/' + logo, 1) }}" border="0"></a></h3>
</td> </td>
<td > <td >

View File

@@ -40,8 +40,8 @@ source_suffix = '.rst'
master_doc = 'index' master_doc = 'index'
# General information about the project. # General information about the project.
project = 'Boost.Python NumPy extension' project = u'Boost.Python NumPy extension'
copyright = '2011, Stefan Seefeld' copyright = u'2011, Stefan Seefeld'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
@@ -181,8 +181,8 @@ html_add_permalinks = False
# Grouping the document tree into LaTeX files. List of tuples # Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]). # (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [ latex_documents = [
('index', 'BoostPythonNumPy.tex', 'Boost.Python NumPy Documentation', ('index', 'BoostPythonNumPy.tex', u'Boost.Python NumPy Documentation',
'Stefan Seefeld', 'manual'), u'Stefan Seefeld', 'manual'),
] ]
# The name of an image file (relative to this directory) to place at the top of # The name of an image file (relative to this directory) to place at the top of
@@ -214,6 +214,6 @@ latex_documents = [
# One entry per manual page. List of tuples # One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section). # (source start file, name, description, authors, manual section).
man_pages = [ man_pages = [
('index', 'boostnumpy', 'Boost.Python NumPy Documentation', ('index', 'boostnumpy', u'Boost.Python NumPy Documentation',
['Stefan Seefeld'], 1) [u'Stefan Seefeld'], 1)
] ]

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 dtype :: We are now ready to create an ndarray with dimensions specified by \*shape\* and of custom dtpye ::
np::ndarray new_array = np::zeros(shape,custom_dtype); np::ndarray new_array = np::zeros(shape,custom_dtype);
} }

View File

@@ -117,7 +117,7 @@ platforms. The complete list of Bjam executables can be found
[h2 Let's Jam!] [h2 Let's Jam!]
__jam__ __jam__
[@../example/Jamroot Here] is our minimalist Jamroot [@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot
file. Simply copy the file and tweak [^use-project boost] to where your file. Simply copy the file and tweak [^use-project boost] to where your
boost root directory is and you're OK. boost root directory is and you're OK.

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 `b2` command either in this directory You may compile these using the `bjam` 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

@@ -3,7 +3,6 @@
# (See accompanying file LICENSE_1_0.txt or copy at # (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt) # http://www.boost.org/LICENSE_1_0.txt)
from __future__ import print_function
import numpy import numpy
import gaussian import gaussian
@@ -20,19 +19,19 @@ x, y = numpy.meshgrid(r, r)
z = g(x, y) z = g(x, y)
s = z.sum() * (r[1] - r[0])**2 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() 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() 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() 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() 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() 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)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #! /usr/bin/env python
# Copyright Stefan Seefeld 2006. Distributed under the Boost # Copyright Stefan Seefeld 2006. Distributed under the Boost
# 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)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #! /usr/bin/env python
# Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost # Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost
# 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)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #! /usr/bin/env python
# Copyright Joel de Guzman 2002-2007. Distributed under the Boost # Copyright Joel de Guzman 2002-2007. Distributed under the Boost
# Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt # Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt
# or copy at http://www.boost.org/LICENSE_1_0.txt) # or copy at http://www.boost.org/LICENSE_1_0.txt)

View File

@@ -16,7 +16,6 @@ from faber.config.try_run import try_run
features += include('include') features += include('include')
features += define('BOOST_ALL_NO_LIB') # disable auto-linking features += define('BOOST_ALL_NO_LIB') # disable auto-linking
features += define('BOOST_NO_AUTO_PTR')
boost_include = options.get_with('boost-include') boost_include = options.get_with('boost-include')
if boost_include: if boost_include:
features += include(boost_include) features += include(boost_include)

View File

@@ -372,11 +372,10 @@ 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 objects::add_doc( return this->make_fn_impl(
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>
@@ -384,11 +383,10 @@ 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 objects::add_doc( return this->make_fn_impl(
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

@@ -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,12 +46,6 @@ 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

@@ -8,8 +8,6 @@
# ifndef BOOST_NO_AUTO_PTR # ifndef BOOST_NO_AUTO_PTR
# include <boost/python/detail/is_xxx.hpp> # include <boost/python/detail/is_xxx.hpp>
# include <memory> # include <memory>
# else
# include <boost/mpl/bool.hpp>
# endif # endif
namespace boost { namespace python { namespace detail { namespace boost { namespace python { namespace detail {

View File

@@ -1,103 +0,0 @@
// 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 <boost/python/detail/prefix.hpp>
#ifdef Py_GIL_DISABLED
// needed for pymutex wrapper
#include <atomic>
#include <cstddef>
#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<unsigned long> 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

View File

@@ -61,8 +61,7 @@ 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

@@ -11,41 +11,11 @@
# ifndef BOOST_PYTHON_MODULE_INIT # ifndef BOOST_PYTHON_MODULE_INIT
namespace boost { namespace python { namespace boost { namespace python { namespace detail {
#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 <typename F, typename... O>
bool gil_not_used_option(F &&, O &&...o);
template <typename... O>
inline bool gil_not_used_option(mod_gil_not_used f, O &&...o) {
return f.flag() || gil_not_used_option(o...);
}
template <typename F, typename... O>
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 # if PY_VERSION_HEX >= 0x03000000
BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)(), bool gil_not_used = false); BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef&, void(*)());
#else #else
@@ -57,37 +27,7 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)());
# if PY_VERSION_HEX >= 0x03000000 # if PY_VERSION_HEX >= 0x03000000
# ifdef HAS_CXX11 # define _BOOST_PYTHON_MODULE_INIT(name) \
# 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)() \ PyObject* BOOST_PP_CAT(PyInit_, name)() \
{ \ { \
static PyModuleDef_Base initial_m_base = { \ static PyModuleDef_Base initial_m_base = { \
@@ -113,7 +53,6 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)());
moduledef, BOOST_PP_CAT(init_module_, name) ); \ moduledef, BOOST_PP_CAT(init_module_, name) ); \
} \ } \
void BOOST_PP_CAT(init_module_, name)() void BOOST_PP_CAT(init_module_, name)()
# endif // HAS_CXX11
# else # else
@@ -127,15 +66,9 @@ BOOST_PYTHON_DECL PyObject* init_module(char const* name, void(*)());
# endif # endif
# if defined(HAS_CXX11) && (PY_VERSION_HEX >= 0x03000000) # define BOOST_PYTHON_MODULE_INIT(name) \
# 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)(); \ void BOOST_PP_CAT(init_module_,name)(); \
extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name) extern "C" BOOST_SYMBOL_EXPORT _BOOST_PYTHON_MODULE_INIT(name)
# endif // HAS_CXX11 && Python 3
# endif # endif

View File

@@ -17,7 +17,6 @@
#include <boost/python/numpy/numpy_object_mgr_traits.hpp> #include <boost/python/numpy/numpy_object_mgr_traits.hpp>
#include <boost/mpl/for_each.hpp> #include <boost/mpl/for_each.hpp>
#include <boost/python/detail/type_traits.hpp> #include <boost/python/detail/type_traits.hpp>
#include <boost/type_traits/is_unsigned.hpp>
namespace boost { namespace python { namespace numpy { namespace boost { namespace python { namespace numpy {

View File

@@ -18,8 +18,6 @@ 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,8 +35,6 @@ 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);
@@ -44,8 +42,6 @@ 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;
@@ -57,7 +53,6 @@ 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 str py_type_str(const python::detail::signature_element &s, const object& current_module_name); static const char * py_type_str(const python::detail::signature_element &s);
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, const object& module_name, bool cpp_types); static str parameter_string(py_function const &f, size_t n, object arg_names, 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

@@ -419,16 +419,6 @@ inline api::object_base& api::object_base::operator=(api::object_base const& rhs
inline api::object_base::~object_base() 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 ); assert( Py_REFCNT(m_ptr) > 0 );
Py_DECREF(m_ptr); Py_DECREF(m_ptr);
} }

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/type_traits/enable_if.hpp> # include <boost/iterator/detail/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::enable_if_<is_object_operators<L,R>::value, T> : boost::iterators::enable_if<is_object_operators<L,R>, 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,7 +96,6 @@ 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

@@ -216,13 +216,7 @@ namespace boost { namespace python { namespace detail {
{ {
for (const_iterator i = proxies.begin(); i != proxies.end(); ++i) for (const_iterator i = proxies.begin(); i != proxies.end(); ++i)
{ {
if ( if ((*i)->ob_refcnt <= 0)
#if PY_VERSION_HEX < 0x03090000
(*i)->ob_refcnt
#else
Py_REFCNT(*i)
#endif
<= 0)
{ {
PyErr_SetString(PyExc_RuntimeError, PyErr_SetString(PyExc_RuntimeError,
"Invariant: Proxy vector in an inconsistent state"); "Invariant: Proxy vector in an inconsistent state");

View File

@@ -11,7 +11,6 @@
#include <boost/python/handle.hpp> #include <boost/python/handle.hpp>
#include <boost/python/detail/raw_pyobject.hpp> #include <boost/python/detail/raw_pyobject.hpp>
#include <boost/python/detail/pymutex.hpp>
#include <boost/python/cast.hpp> #include <boost/python/cast.hpp>
#include <vector> #include <vector>
@@ -146,8 +145,6 @@ namespace
inline bool visit(rvalue_from_python_chain const* chain) 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); visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain);
if (p != visited.end() && *p == chain) if (p != visited.end() && *p == chain)
return false; return false;
@@ -160,11 +157,9 @@ namespace
{ {
unvisit(rvalue_from_python_chain const* chain) unvisit(rvalue_from_python_chain const* chain)
: chain(chain) {} : chain(chain) {}
~unvisit() ~unvisit()
{ {
BOOST_PYTHON_LOCK_STATE();
visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain); visited_t::iterator const p = std::lower_bound(visited.begin(), visited.end(), chain);
assert(p != visited.end()); assert(p != visited.end());
visited.erase(p); visited.erase(p);
@@ -227,13 +222,7 @@ namespace
, char const* ref_type) , char const* ref_type)
{ {
handle<> holder(source); handle<> holder(source);
if ( if (source->ob_refcnt <= 1)
#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

@@ -5,7 +5,6 @@
#include <boost/python/converter/registry.hpp> #include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp> #include <boost/python/converter/registrations.hpp>
#include <boost/python/converter/builtin_converters.hpp> #include <boost/python/converter/builtin_converters.hpp>
#include <boost/python/detail/pymutex.hpp>
#include <set> #include <set>
#include <stdexcept> #include <stdexcept>
@@ -113,9 +112,9 @@ registration::~registration()
namespace // <unnamed> namespace // <unnamed>
{ {
typedef registration entry; typedef registration entry;
typedef std::set<entry> registry_t; typedef std::set<entry> registry_t;
#ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND #ifndef BOOST_PYTHON_CONVERTER_REGISTRY_APPLE_MACH_WORKAROUND
registry_t& entries() registry_t& entries()
{ {
@@ -182,8 +181,6 @@ namespace // <unnamed>
entry* get(type_info type, bool is_shared_ptr = false) entry* get(type_info type, bool is_shared_ptr = false)
{ {
BOOST_PYTHON_LOCK_STATE();
# ifdef BOOST_PYTHON_TRACE_REGISTRY # ifdef BOOST_PYTHON_TRACE_REGISTRY
registry_t::iterator p = entries().find(entry(type)); registry_t::iterator p = entries().find(entry(type));
@@ -296,8 +293,6 @@ namespace registry
registration const* query(type_info type) registration const* query(type_info type)
{ {
BOOST_PYTHON_LOCK_STATE();
registry_t::iterator p = entries().find(entry(type)); registry_t::iterator p = entries().find(entry(type));
# ifdef BOOST_PYTHON_TRACE_REGISTRY # ifdef BOOST_PYTHON_TRACE_REGISTRY
std::cout << "querying " << type std::cout << "querying " << type

View File

@@ -5,7 +5,6 @@
#include <boost/python/type_id.hpp> #include <boost/python/type_id.hpp>
#include <boost/python/detail/decorated_type_id.hpp> #include <boost/python/detail/decorated_type_id.hpp>
#include <boost/python/detail/pymutex.hpp>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
@@ -82,7 +81,7 @@ namespace
{ {
free_mem(char*p) free_mem(char*p)
: p(p) {} : p(p) {}
~free_mem() ~free_mem()
{ {
std::free(p); std::free(p);
@@ -93,7 +92,6 @@ namespace
bool cxxabi_cxa_demangle_is_broken() bool cxxabi_cxa_demangle_is_broken()
{ {
BOOST_PYTHON_LOCK_STATE();
static bool was_tested = false; static bool was_tested = false;
static bool is_broken = false; static bool is_broken = false;
if (!was_tested) { if (!was_tested) {
@@ -111,8 +109,6 @@ namespace detail
{ {
BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled) BOOST_PYTHON_DECL char const* gcc_demangle(char const* mangled)
{ {
BOOST_PYTHON_LOCK_STATE();
typedef std::vector< typedef std::vector<
std::pair<char const*, char const*> std::pair<char const*, char const*>
> mangling_map; > mangling_map;

View File

@@ -68,16 +68,8 @@ object dict_base::get(object_cref k) const
{ {
if (check_exact(this)) 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()); PyObject* result = PyDict_GetItem(this->ptr(),k.ptr());
return object(detail::borrowed_reference(result ? result : Py_None)); return object(detail::borrowed_reference(result ? result : Py_None));
#endif
} }
else else
{ {

View File

@@ -10,21 +10,9 @@
#include <boost/python/errors.hpp> #include <boost/python/errors.hpp>
#include <boost/cast.hpp> #include <boost/cast.hpp>
#include <boost/python/detail/exception_handler.hpp> #include <boost/python/detail/exception_handler.hpp>
#include <boost/python/detail/pymutex.hpp>
namespace boost { namespace python { 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() {} error_already_set::~error_already_set() {}
// IMPORTANT: this function may only be called from within a catch block! // IMPORTANT: this function may only be called from within a catch block!
@@ -32,13 +20,8 @@ BOOST_PYTHON_DECL bool handle_exception_impl(function0<void> f)
{ {
try try
{ {
detail::exception_handler* handler_chain = nullptr; if (detail::exception_handler::chain)
{ return detail::exception_handler::chain->handle(f);
BOOST_PYTHON_LOCK_STATE();
handler_chain = detail::exception_handler::chain;
}
if (handler_chain)
return handler_chain->handle(f);
f(); f();
return false; return false;
} }
@@ -97,7 +80,6 @@ exception_handler::exception_handler(handler_function const& impl)
: m_impl(impl) : m_impl(impl)
, m_next(0) , m_next(0)
{ {
BOOST_PYTHON_LOCK_STATE();
if (chain != 0) if (chain != 0)
tail->m_next = this; tail->m_next = this;
else else

View File

@@ -38,17 +38,10 @@ BOOST_PYTHON_DECL void scope_setattr_doc(char const* name, object const& x, char
#if PY_VERSION_HEX >= 0x03000000 #if PY_VERSION_HEX >= 0x03000000
BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef& moduledef, BOOST_PYTHON_DECL PyObject* init_module(PyModuleDef& moduledef, void(*init_function)())
void(*init_function)(), bool gil_not_used)
{ {
PyObject *mod = PyModule_Create(&moduledef);
#ifdef Py_GIL_DISABLED
if (mod != NULL && gil_not_used) {
PyUnstable_Module_SetGIL(mod, Py_MOD_GIL_NOT_USED);
}
#endif
return init_module_in_scope( return init_module_in_scope(
mod, PyModule_Create(&moduledef),
init_function); init_function);
} }

View File

@@ -98,16 +98,35 @@ 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 { int dtype::get_itemsize() const { return reinterpret_cast<PyArray_Descr*>(ptr())->elsize;}
#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) {
return a == 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<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

@@ -333,9 +333,8 @@ 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, q); instance_holder::deallocate(inst, dynamic_cast<void*>(p));
} }
// Python 2.2.1 won't add weak references automatically when // Python 2.2.1 won't add weak references automatically when
@@ -503,16 +502,6 @@ 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
@@ -575,9 +564,6 @@ 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;
@@ -767,9 +753,10 @@ void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std:
throw std::bad_alloc(); throw std::bad_alloc();
const uintptr_t x = reinterpret_cast<uintptr_t>(base_storage) + sizeof(alignment_marker_t); 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 //this has problems for x -> max(void *)
// Since the alignment is a power of two, the formula can be simplified with bitwise AND operator as follow: //const size_t padding = alignment - ((x + sizeof(alignment_marker_t)) % alignment);
const uintptr_t padding = (alignment - (x & (alignment - 1))) & (alignment - 1); //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; const size_t aligned_offset = sizeof(alignment_marker_t) + padding;
void* const aligned_storage = (char *)base_storage + aligned_offset; void* const aligned_storage = (char *)base_storage + aligned_offset;
BOOST_ASSERT((char *) aligned_storage + holder_size <= (char *)base_storage + base_allocation); BOOST_ASSERT((char *) aligned_storage + holder_size <= (char *)base_storage + base_allocation);

View File

@@ -49,9 +49,7 @@ extern "C"
if (!self->name) if (!self->name)
{ {
return return
#if PY_VERSION_HEX >= 0x03030000 #if PY_VERSION_HEX >= 0x03000000
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_));
@@ -64,9 +62,7 @@ extern "C"
return 0; return 0;
return return
#if PY_VERSION_HEX >= 0x03030000 #if PY_VERSION_HEX >= 0x03000000
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",
@@ -149,7 +145,6 @@ static PyTypeObject enum_type_object = {
}; };
object module_prefix(); object module_prefix();
object qualname(const char *name);
namespace namespace
{ {
@@ -180,11 +175,6 @@ 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

@@ -161,6 +161,7 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const
else else
{ {
// build a new arg tuple, will adjust its size later // build a new arg tuple, will adjust its size later
assert(max_arity <= static_cast<std::size_t>(ssize_t_max));
inner_args = handle<>( inner_args = handle<>(
PyTuple_New(static_cast<ssize_t>(max_arity))); PyTuple_New(static_cast<ssize_t>(max_arity)));
@@ -418,30 +419,6 @@ 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)
{ {
@@ -512,24 +489,11 @@ 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*>( allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast<char*>("__name__"))));
#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)
@@ -568,7 +532,24 @@ void function::add_to_namespace(
"C++ signature:", f->signature(true))); "C++ signature:", f->signature(true)));
} }
*/ */
add_doc(attribute, 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;
}
} }
BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL void add_to_namespace(
@@ -583,18 +564,6 @@ 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
{ {
@@ -701,7 +670,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_module(); object const& ns = f->get_namespace();
if (!ns.is_none()) { if (!ns.is_none()) {
return python::incref(ns.ptr()); return python::incref(ns.ptr());
} }

View File

@@ -114,58 +114,23 @@ namespace boost { namespace python { namespace objects {
return res; return res;
} }
static str get_qualname(const PyTypeObject *py_type) const char * function_doc_signature_generator::py_type_str(const python::detail::signature_element &s)
{
# 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 str(none); return 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 )
str name(get_qualname(py_type)); return py_type->tp_name;
if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) { else{
// Qualify the type name if it is defined in a different 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(
type_module_name,
current_module_name.ptr(),
Py_NE
) != 0
) {
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 {
static const char * object = "object"; static const char * object = "object";
return str(object); return object;
} }
} }
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 function_doc_signature_generator::parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types)
{ {
str param; str param;
@@ -191,12 +156,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], current_module_name),kv[0]) ); param = str( " (%s)%s" % make_tuple(py_type_str(s[n]),kv[0]) );
else else
param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n], current_module_name),"arg", n) ); param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n]),"arg", n) );
} }
else //we are processing the return type else //we are processing the return type
param = py_type_str(f.get_return_type(), current_module_name); param = py_type_str(f.get_return_type());
} }
//an argument - check for default value and append it //an argument - check for default value and append it
@@ -234,7 +199,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, f->get_module(), cpp_types) parameter_string(impl, n, f->m_arg_names, 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

@@ -4,7 +4,6 @@
// http://www.boost.org/LICENSE_1_0.txt) // http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/object/inheritance.hpp> #include <boost/python/object/inheritance.hpp>
#include <boost/python/type_id.hpp> #include <boost/python/type_id.hpp>
#include <boost/python/detail/pymutex.hpp>
#include <boost/graph/breadth_first_search.hpp> #include <boost/graph/breadth_first_search.hpp>
#if _MSC_FULL_VER >= 13102171 && _MSC_FULL_VER <= 13102179 #if _MSC_FULL_VER >= 13102171 && _MSC_FULL_VER <= 13102179
# include <boost/graph/reverse_graph.hpp> # include <boost/graph/reverse_graph.hpp>
@@ -391,8 +390,6 @@ namespace
inline void* convert_type(void* const p, class_id src_t, class_id dst_t, bool polymorphic) 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 // Quickly rule out unregistered types
index_entry* src_p = seek_type(src_t); index_entry* src_p = seek_type(src_t);
if (src_p == 0) if (src_p == 0)
@@ -455,8 +452,6 @@ BOOST_PYTHON_DECL void* find_static_type(void* p, class_id src_t, class_id dst_t
BOOST_PYTHON_DECL void add_cast( BOOST_PYTHON_DECL void add_cast(
class_id src_t, class_id dst_t, cast_function cast, bool is_downcast) 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 // adding an edge will invalidate any record of unreachability in
// the cache. // the cache.
static std::size_t expected_cache_len = 0; static std::size_t expected_cache_len = 0;
@@ -495,7 +490,6 @@ BOOST_PYTHON_DECL void add_cast(
BOOST_PYTHON_DECL void register_dynamic_id_aux( BOOST_PYTHON_DECL void register_dynamic_id_aux(
class_id static_id, dynamic_id_function get_dynamic_id) class_id static_id, dynamic_id_function get_dynamic_id)
{ {
BOOST_PYTHON_LOCK_STATE();
tuples::get<kdynamic_id>(*demand_type(static_id)) = get_dynamic_id; tuples::get<kdynamic_id>(*demand_type(static_id)) = get_dynamic_id;
} }

View File

@@ -34,14 +34,4 @@ 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

@@ -21,28 +21,20 @@ namespace detail
this->m_self, const_cast<char*>(name)))) this->m_self, const_cast<char*>(name))))
) )
{ {
PyObject* class_f = 0; PyObject* borrowed_f = 0;
if ( if (
PyMethod_Check(m.get()) PyMethod_Check(m.get())
&& PyMethod_GET_SELF(m.get()) == this->m_self && PyMethod_GET_SELF(m.get()) == this->m_self
&& class_object->tp_dict != 0 && class_object->tp_dict != 0
) )
{ {
#if PY_VERSION_HEX >= 0x030D0000 borrowed_f = ::PyDict_GetItemString(
if (::PyDict_GetItemStringRef(
class_object->tp_dict, const_cast<char*>(name), &class_f) < 0) {
throw_error_already_set();
}
#else
class_f = ::PyDict_GetItemString(
class_object->tp_dict, const_cast<char*>(name)); class_object->tp_dict, const_cast<char*>(name));
Py_XINCREF(class_f);
#endif
} }
bool is_override = (class_f != PyMethod_GET_FUNCTION(m.get())); if (borrowed_f != PyMethod_GET_FUNCTION(m.get()))
Py_XDECREF(class_f);
if (is_override)
return override(m); return override(m);
} }
} }

View File

@@ -2,16 +2,14 @@
# 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 : requires ; import ../../config/checks/config : requires ;
lib socket ; lib socket ;
project use-project /boost/python : ../build ;
project /boost/python/test
: requirements : requirements
<toolset>gcc:<cxxflags>-Wextra <toolset>gcc:<cxxflags>-Wextra
<target-os>qnxnto:<library>socket <target-os>qnxnto:<library>socket
@@ -30,7 +28,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
] ; ] ;
} }
@@ -54,18 +52,6 @@ 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
: :
@@ -111,8 +97,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 ]
] ]
@@ -133,7 +119,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 ]
@@ -206,13 +192,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)
@@ -226,29 +212,28 @@ bpl-test crossmod_opaque
# --- unit tests of library components --- # --- unit tests of library components ---
[ compile indirect_traits_test.cpp : <use>base_deps ] [ compile indirect_traits_test.cpp ]
[ run destroy_test.cpp : : : <use>base_deps ] [ run destroy_test.cpp ]
[ 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 : : : <use>base_deps ] [ run if_else.cpp ]
[ py-run pointee.cpp ] [ py-run pointee.cpp ]
[ run result.cpp : : : <use>base_deps ] [ run result.cpp ]
[ compile string_literal.cpp : <use>base_deps ] [ compile string_literal.cpp ]
[ 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
] ]

View File

@@ -99,7 +99,7 @@ BOOST_PYTHON_MODULE(back_reference_ext)
.def("set", &Y::set) .def("set", &Y::set)
; ;
class_<Z,std::shared_ptr<Z> >("Z", init<int>()) class_<Z,std::auto_ptr<Z> >("Z", init<int>())
.def("value", &Z::value) .def("value", &Z::value)
.def("set", &Z::set) .def("set", &Z::set)
; ;

View File

@@ -9,13 +9,14 @@
struct foo struct foo
{ {
operator std::shared_ptr<int>&() const; operator std::auto_ptr<int>&() const;
}; };
int main() int main()
{ {
using namespace boost::python::detail; using namespace boost::python::detail;
BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<int>::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<int>::value);
BOOST_STATIC_ASSERT(copy_ctor_mutates_rhs<std::auto_ptr<int> >::value);
BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<std::string>::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<std::string>::value);
BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<foo>::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs<foo>::value);
return 0; return 0;

View File

@@ -68,7 +68,6 @@ for t in [('injected',),
('raw_ctor',), ('raw_ctor',),
('exception_translator',), ('exception_translator',),
('module_init_exception',), ('module_init_exception',),
('module_nogil',),
('test_enum', ['enum_ext']), ('test_enum', ['enum_ext']),
('test_cltree', ['cltree']), ('test_cltree', ['cltree']),
('newtest', ['m1', 'm2']), ('newtest', ['m1', 'm2']),
@@ -119,10 +118,10 @@ for t in [('injected',),
tests.append(extension_test('shared_ptr', tests.append(extension_test('shared_ptr',
condition=set.define.contains('HAS_CXX11'))) condition=set.define.contains('HAS_CXX11')))
#tests.append(extension_test('polymorphism2_auto_ptr', tests.append(extension_test('polymorphism2_auto_ptr',
# condition=set.define.contains('HAS_CXX11').not_())) condition=set.define.contains('HAS_CXX11').not_()))
#tests.append(extension_test('auto_ptr', tests.append(extension_test('auto_ptr',
# condition=set.define.contains('HAS_CXX11'))) condition=set.define.contains('HAS_CXX11')))
import_ = binary('import_', ['import_.cpp', src.bpl], features=features|python_libs) import_ = binary('import_', ['import_.cpp', src.bpl], features=features|python_libs)
if platform.os == 'Windows': if platform.os == 'Windows':

View File

@@ -17,7 +17,7 @@ typedef test_class<> X;
X* empty() { return new X(1000); } X* empty() { return new X(1000); }
std::shared_ptr<X> sum(int a, int b) { return std::shared_ptr<X>(new X(a+b)); } std::auto_ptr<X> sum(int a, int b) { return std::auto_ptr<X>(new X(a+b)); }
boost::shared_ptr<X> product(int a, int b, int c) boost::shared_ptr<X> product(int a, int b, int c)
{ {

View File

@@ -214,13 +214,6 @@ 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

@@ -1,25 +0,0 @@
// Test for BOOST_PYTHON_MODULE with optional mod_gil_not_used argument
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
// 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

View File

@@ -1,29 +0,0 @@
"""
>>> 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)

View File

@@ -4,8 +4,6 @@
// 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"
@@ -18,8 +16,6 @@
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();
@@ -30,13 +26,11 @@ 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>())
@@ -48,17 +42,6 @@ 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,35 +13,14 @@
>>> X.__name__ >>> X.__name__
'X' 'X'
>>> X.Y # doctest: +py2 >>> X.Y
<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 :'
''' '''
@@ -51,23 +30,7 @@ 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

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# Copyright Jim Bosch & Ankit Daftery 2010-2012. # Copyright Jim Bosch & Ankit Daftery 2010-2012.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
@@ -15,7 +15,7 @@ if (sys.version_info.major >= 3):
class DtypeTestCase(unittest.TestCase): class DtypeTestCase(unittest.TestCase):
def assertEquivalent(self, a, b): def assertEquivalent(self, a, b):
return self.assertTrue(dtype_ext.equivalent(a, b), "%r is not equivalent to %r") return self.assert_(dtype_ext.equivalent(a, b), "%r is not equivalent to %r")
def testIntegers(self): def testIntegers(self):
for bits in (8, 16, 32, 64): for bits in (8, 16, 32, 64):

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# Copyright Jim Bosch & Ankit Daftery 2010-2012. # Copyright Jim Bosch & Ankit Daftery 2010-2012.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# Copyright Jim Bosch & Ankit Daftery 2010-2012. # Copyright Jim Bosch & Ankit Daftery 2010-2012.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
@@ -19,7 +19,7 @@ class TestNdarray(unittest.TestCase):
a1 = ndarray_ext.zeros(shape,dt) a1 = ndarray_ext.zeros(shape,dt)
a2 = v.reshape(a1.shape) a2 = v.reshape(a1.shape)
self.assertEqual(shape,a1.shape) self.assertEqual(shape,a1.shape)
self.assertTrue((a1 == a2).all()) self.assert_((a1 == a2).all())
def testNdzeros_matrix(self): def testNdzeros_matrix(self):
for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128):
@@ -28,7 +28,7 @@ class TestNdarray(unittest.TestCase):
a1 = ndarray_ext.zeros_matrix(shape, dt) a1 = ndarray_ext.zeros_matrix(shape, dt)
a2 = numpy.matrix(numpy.zeros(shape, dtype=dtp)) a2 = numpy.matrix(numpy.zeros(shape, dtype=dtp))
self.assertEqual(shape,a1.shape) self.assertEqual(shape,a1.shape)
self.assertTrue((a1 == a2).all()) self.assert_((a1 == a2).all())
self.assertEqual(type(a1), type(a2)) self.assertEqual(type(a1), type(a2))
def testNdarray(self): def testNdarray(self):
@@ -38,8 +38,8 @@ class TestNdarray(unittest.TestCase):
dt = numpy.dtype(dtp) dt = numpy.dtype(dtp)
a1 = ndarray_ext.array(a) a1 = ndarray_ext.array(a)
a2 = ndarray_ext.array(a,dt) a2 = ndarray_ext.array(a,dt)
self.assertTrue((a1 == v).all()) self.assert_((a1 == v).all())
self.assertTrue((a2 == v).all()) self.assert_((a2 == v).all())
for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)): for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)):
a1 = a1.reshape(shape) a1 = a1.reshape(shape)
self.assertEqual(shape,a1.shape) self.assertEqual(shape,a1.shape)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# Copyright Jim Bosch & Ankit Daftery 2010-2012. # Copyright Jim Bosch & Ankit Daftery 2010-2012.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# Copyright Jim Bosch & Ankit Daftery 2010-2012. # Copyright Jim Bosch & Ankit Daftery 2010-2012.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
@@ -18,7 +18,7 @@ class TestTemplates(unittest.TestCase):
a1 = numpy.zeros(shape, dtype=dtype) a1 = numpy.zeros(shape, dtype=dtype)
a2 = v.reshape(a1.shape) a2 = v.reshape(a1.shape)
templates_ext.fill(a1) templates_ext.fill(a1)
self.assertTrue((a1 == a2).all()) self.assert_((a1 == a2).all())
a1 = numpy.zeros((12,), dtype=numpy.float64) a1 = numpy.zeros((12,), dtype=numpy.float64)
self.assertRaises(TypeError, templates_ext.fill, a1) self.assertRaises(TypeError, templates_ext.fill, a1)
a1 = numpy.zeros((12,2,3), dtype=numpy.float32) a1 = numpy.zeros((12,2,3), dtype=numpy.float32)

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python
# Copyright Jim Bosch & Ankit Daftery 2010-2012. # Copyright Jim Bosch & Ankit Daftery 2010-2012.
# Distributed under the Boost Software License, Version 1.0. # Distributed under the Boost Software License, Version 1.0.
@@ -8,10 +8,7 @@
import ufunc_ext import ufunc_ext
import unittest import unittest
import numpy import numpy
try: from numpy.testing.utils import assert_array_almost_equal
from numpy.testing import assert_array_almost_equal
except ImportError:
from numpy.testing.utils import assert_array_almost_equal
class TestUnary(unittest.TestCase): class TestUnary(unittest.TestCase):
@@ -27,7 +24,7 @@ class TestUnary(unittest.TestCase):
assert_array_almost_equal(b, a*2.0) assert_array_almost_equal(b, a*2.0)
c = numpy.zeros(5, dtype=float) c = numpy.zeros(5, dtype=float)
d = f(a,output=c) d = f(a,output=c)
self.assertTrue((c == d).all()) self.assert_(c is d)
assert_array_almost_equal(d, a*2.0) assert_array_almost_equal(d, a*2.0)
def testList(self): def testList(self):
@@ -50,7 +47,7 @@ class TestBinary(unittest.TestCase):
assert_array_almost_equal(f(a,b), (a*2+b*3)) assert_array_almost_equal(f(a,b), (a*2+b*3))
c = numpy.zeros(5, dtype=float) c = numpy.zeros(5, dtype=float)
d = f(a,b,output=c) d = f(a,b,output=c)
self.assertTrue((c == d).all()) self.assert_(c is d)
assert_array_almost_equal(d, a*2 + b*3) 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(a, 2.0), a*2 + 6.0)
assert_array_almost_equal(f(1.0, b), 2.0 + b*3) assert_array_almost_equal(f(1.0, b), 2.0 + b*3)

View File

@@ -36,7 +36,7 @@ BOOST_PYTHON_MODULE( operators_wrapper_ext )
; ;
scope().attr("v") = vector(); scope().attr("v") = vector();
std::shared_ptr<vector> dp(new dvector); std::auto_ptr<vector> dp(new dvector);
register_ptr_to_python< std::shared_ptr<vector> >(); register_ptr_to_python< std::auto_ptr<vector> >();
scope().attr("d") = dp; scope().attr("d") = dp;
} }

View File

@@ -9,10 +9,8 @@ r'''>>> import pickle1_ext
1 1
>>> pickle1_ext.world.__name__ >>> pickle1_ext.world.__name__
'world' 'world'
>>> pickle1_ext.world('Hello').__reduce__() # doctest: +PY310 >>> pickle1_ext.world('Hello').__reduce__()
(<class 'pickle1_ext.world'>, ('Hello',)) (<class 'pickle1_ext.world'>, ('Hello',))
>>> pickle1_ext.world('Hello').__reduce__() # doctest: +PY311
(<class 'pickle1_ext.world'>, ('Hello',), None)
>>> wd = pickle1_ext.world('California') >>> wd = pickle1_ext.world('California')
>>> pstr = pickle.dumps(wd) >>> pstr = pickle.dumps(wd)
>>> wl = pickle.loads(pstr) >>> wl = pickle.loads(pstr)
@@ -33,27 +31,7 @@ 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__))
# > 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__': if __name__ == '__main__':
print("running...") print("running...")

View File

@@ -12,10 +12,8 @@ r'''>>> import pickle4_ext
1 1
>>> pickle4_ext.world.__name__ >>> pickle4_ext.world.__name__
'world' 'world'
>>> pickle4_ext.world('Hello').__reduce__() # doctest: +PY310 >>> pickle4_ext.world('Hello').__reduce__()
(<class 'pickle4_ext.world'>, ('Hello',)) (<class 'pickle4_ext.world'>, ('Hello',))
>>> pickle4_ext.world('Hello').__reduce__() # doctest: +PY311
(<class 'pickle4_ext.world'>, ('Hello',), None)
>>> wd = pickle4_ext.world('California') >>> wd = pickle4_ext.world('California')
>>> pstr = pickle.dumps(wd) >>> pstr = pickle.dumps(wd)
>>> wl = pickle.loads(pstr) >>> wl = pickle.loads(pstr)
@@ -31,27 +29,7 @@ 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__))
# > 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__': if __name__ == '__main__':
print("running...") print("running...")

View File

@@ -64,7 +64,6 @@ 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,9 +20,6 @@ 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
@@ -56,10 +53,11 @@ class instance count from object:
1 1
as expected you can't assign new value to read only property as expected you can't assign new value to read only property
>>> x1.value_r = 2 # doctest: +ELLIPSIS >>> x1.value_r = 2
Traceback (most recent call last): Traceback (most recent call last):
... File "properties.py", line 49, in ?
AttributeError: ... x1.value_r = 2
AttributeError: can't set attribute
setting value_rw to 2. value_direct: setting value_rw to 2. value_direct:
>>> x1.value_rw = 2 >>> x1.value_rw = 2
@@ -86,27 +84,8 @@ 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

@@ -62,14 +62,14 @@ int test_main(int, char * [])
assert_holder<Base,Derived assert_holder<Base,Derived
,value_holder_back_reference<Base,Derived> >(); ,value_holder_back_reference<Base,Derived> >();
assert_holder<Base,std::unique_ptr<Base> assert_holder<Base,std::auto_ptr<Base>
,pointer_holder<std::unique_ptr<Base>,Base> >(); ,pointer_holder<std::auto_ptr<Base>,Base> >();
assert_holder<Base,std::unique_ptr<Derived> assert_holder<Base,std::auto_ptr<Derived>
,pointer_holder_back_reference<std::unique_ptr<Derived>,Base> >(); ,pointer_holder_back_reference<std::auto_ptr<Derived>,Base> >();
assert_holder<BR,std::unique_ptr<BR> assert_holder<BR,std::auto_ptr<BR>
,pointer_holder_back_reference<std::unique_ptr<BR>,BR> > (); ,pointer_holder_back_reference<std::auto_ptr<BR>,BR> > ();
return 0; return 0;
} }

View File

@@ -38,7 +38,7 @@
12 12
>>> try: modify(p) >>> try: modify(p)
... except TypeError: pass ... except TypeError: pass
... else: print('expected a TypeError') ... else: 'print(expected a TypeError)'
>>> look(None) >>> look(None)
-1 -1
>>> store(p) >>> store(p)
@@ -61,7 +61,7 @@ bye
13 13
>>> try: modify(z) >>> try: modify(z)
... except TypeError: pass ... except TypeError: pass
... else: print('expected a TypeError') ... else: 'print(expected a TypeError)'
>>> Z.get() # should be None >>> Z.get() # should be None
>>> store(z) >>> store(z)
@@ -84,7 +84,7 @@ bye
17 17
>>> try: modify(x) >>> try: modify(x)
... except TypeError: pass ... except TypeError: pass
... else: print('expected a TypeError') ... else: 'print(expected a TypeError)'
>>> look(None) >>> look(None)
-1 -1
>>> store(x) >>> store(x)

View File

@@ -33,8 +33,6 @@ 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.

View File

@@ -1,7 +1,7 @@
# Copyright David Abrahams 2004. Distributed under the Boost # Copyright David Abrahams 2004. Distributed under the Boost
# 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)
#!/usr/bin/env python3 #!/usr/bin/env python
from cltree import basic,symbol,constant,variable from cltree import basic,symbol,constant,variable

View File

@@ -13,7 +13,7 @@ int main()
{ {
PyTypeObject o; PyTypeObject o;
Y y; Y y;
BOOST_TEST(boost::python::upcast<PyObject>(&o) == reinterpret_cast<PyObject*>(&o)); BOOST_TEST(&Py_REFCNT(boost::python::upcast<PyObject>(&o)) == &Py_REFCNT(&o));
BOOST_TEST(boost::python::upcast<PyObject>(&y) == &y); BOOST_TEST(&Py_REFCNT(boost::python::upcast<PyObject>(&y)) == &Py_REFCNT(&y));
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -20,12 +20,12 @@ struct data
} }
}; };
std::shared_ptr<data> create_data() std::auto_ptr<data> create_data()
{ {
return std::shared_ptr<data>( new data ); return std::auto_ptr<data>( new data );
} }
void do_nothing( std::shared_ptr<data>& ){} void do_nothing( std::auto_ptr<data>& ){}
namespace bp = boost::python; namespace bp = boost::python;
@@ -59,7 +59,7 @@ struct data_wrapper : data, bp::wrapper< data >
BOOST_PYTHON_MODULE(wrapper_held_type_ext) BOOST_PYTHON_MODULE(wrapper_held_type_ext)
{ {
bp::class_< data_wrapper, std::shared_ptr< data > >( "data" ) bp::class_< data_wrapper, std::auto_ptr< data > >( "data" )
.def( "id", &data::id, &::data_wrapper::default_id ); .def( "id", &data::id, &::data_wrapper::default_id );
bp::def( "do_nothing", &do_nothing ); bp::def( "do_nothing", &do_nothing );