diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index ffcd7e3b59..0000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,111 +0,0 @@ -environment: - global: - # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the - # /E:ON and /V:ON options are not enabled in the batch script intepreter - # See: http://stackoverflow.com/a/13751649/163740 - CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci\\run_with_env.cmd" - - matrix: - - # Pre-installed Python versions, which Appveyor may upgrade to - # a later point release. - # See: http://www.appveyor.com/docs/installed-software#python - - - PYTHON: C:\\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - MSVC: 12.0 - ARCH: x86_64 - BOOST_PREFIX: C:\Libraries\boost_1_66_0 - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - PYTHON: C:\\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - MSVC: 15.9.19 - ARCH: x86_64 - BOOST_PREFIX: C:\Libraries\boost_1_69_0 - - - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - PYTHON: C:\\Python36-x64 - PYTHON_VERSION: 3.6.x - PYTHON_ARCH: 64 - MSVC: 16.7.4 - ARCH: x86_64 - BOOST_PREFIX: C:\Libraries\boost_1_73_0 - -install: - # If there is a newer build queued for the same PR, cancel this one. - # The AppVeyor 'rollout builds' option is supposed to serve the same - # purpose but it is problematic because it tends to cancel builds pushed - # directly to master instead of just PR builds (or the converse). - # credits: JuliaLang developers. - - ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod ` - https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` - Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` - throw "There are newer queued builds for this pull request, failing early." } - - ECHO "Filesystem root:" - - ps: "ls \"C:/\"" - - ECHO "Installed libraries:" - - ps: "ls \"C:/Libraries/\"" - ## This path doesn't exist with the VS 2017 worker images - #- ECHO "Installed SDKs:" - #- ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" - - # Install Python (from the official .msi of http://python.org) and pip when - # not already installed. - - ps: if (-not(Test-Path($env:PYTHON))) { & .ci\install.ps1 } - - # Prepend newly installed Python to the PATH of this build (this cannot be - # done from inside the powershell script as it would require to restart - # the parent CMD process). - - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" - - # Check that we have the expected version and architecture for Python - - "python --version" - - "python -c \"import struct; print(struct.calcsize('P') * 8)\"" - - # Upgrade to the latest version of pip to avoid it displaying warnings - # about it being out of date. - - "python -m pip install --disable-pip-version-check --user --upgrade pip" - - # Install the build dependencies of the project. If some dependencies contain - # compiled extensions and are not provided as pre-built wheel packages, - # pip will build them from source using the MSVC compiler matching the - # target Python version and architecture - - - curl -LfsS -o vswhere.exe https://github.com/Microsoft/vswhere/releases/download/2.8.4/vswhere.exe - #- | - # curl -LfsS -o faber.tar.gz https://github.com/stefanseefeld/faber/archive/snapshot/2020-08-01.tar.gz - # tar xf faber.tar.gz - # CD faber-snapshot-2020-08-01 - # python setup.py install - # CD .. - - python -m pip install faber - # report the available MSVC compilers - - faber --log=tools --info=tools cxx - - easy_install sphinx - - python -m pip install numpy - - set FARGS=--log=summary --log=output --log=actions --log=commands --with-boost-include=%BOOST_PREFIX% target.arch=%ARCH% cxx.name=msvc cxx.version=%MSVC% - -build_script: - - faber %FARGS% config || type config.log - - faber %FARGS% -j8 - -test_script: - - faber %FARGS% -j8 test.report - -after_test: - # If tests are successful, create binary packages for the project. - #- "%CMD_IN_ENV% python setup.py bdist_wheel" - #- "%CMD_IN_ENV% python setup.py bdist_wininst" - #- "%CMD_IN_ENV% python setup.py bdist_msi" - #- ps: "ls dist" - -#artifacts: - # Archive the generated packages in the ci.appveyor.com build report. - #- path: dist\* - -#on_success: -# - TODO: upload the content of dist/*.whl to a public wheelhouse -# diff --git a/.ci/faber b/.ci/faber index b23e8a18ba..ddb36ddf66 100644 --- a/.ci/faber +++ b/.ci/faber @@ -1,3 +1,7 @@ +# -*- python -*- + +from faber.tools.boost import boostbook from faber.tools.python import python +bb = boostbook(prefix='/usr/share/boostbook') p = python(command='$PYTHON') diff --git a/.ci/install.ps1 b/.ci/install.ps1 deleted file mode 100644 index 94d6f01813..0000000000 --- a/.ci/install.ps1 +++ /dev/null @@ -1,229 +0,0 @@ -# Sample script to install Python and pip under Windows -# Authors: Olivier Grisel, Jonathan Helmus, Kyle Kastner, and Alex Willmer -# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ - -$MINICONDA_URL = "http://repo.continuum.io/miniconda/" -$BASE_URL = "https://www.python.org/ftp/python/" -$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" -$GET_PIP_PATH = "C:\get-pip.py" - -$PYTHON_PRERELEASE_REGEX = @" -(?x) -(?\d+) -\. -(?\d+) -\. -(?\d+) -(?[a-z]{1,2}\d+) -"@ - - -function Download ($filename, $url) { - $webclient = New-Object System.Net.WebClient - - $basedir = $pwd.Path + "\" - $filepath = $basedir + $filename - if (Test-Path $filename) { - Write-Host "Reusing" $filepath - return $filepath - } - - # Download and retry up to 3 times in case of network transient errors. - Write-Host "Downloading" $filename "from" $url - $retry_attempts = 2 - for ($i = 0; $i -lt $retry_attempts; $i++) { - try { - $webclient.DownloadFile($url, $filepath) - break - } - Catch [Exception]{ - Start-Sleep 1 - } - } - if (Test-Path $filepath) { - Write-Host "File saved at" $filepath - } else { - # Retry once to get the error message if any at the last try - $webclient.DownloadFile($url, $filepath) - } - return $filepath -} - - -function ParsePythonVersion ($python_version) { - if ($python_version -match $PYTHON_PRERELEASE_REGEX) { - return ([int]$matches.major, [int]$matches.minor, [int]$matches.micro, - $matches.prerelease) - } - $version_obj = [version]$python_version - return ($version_obj.major, $version_obj.minor, $version_obj.build, "") -} - - -function DownloadPython ($python_version, $platform_suffix) { - $major, $minor, $micro, $prerelease = ParsePythonVersion $python_version - - if (($major -le 2 -and $micro -eq 0) ` - -or ($major -eq 3 -and $minor -le 2 -and $micro -eq 0) ` - ) { - $dir = "$major.$minor" - $python_version = "$major.$minor$prerelease" - } else { - $dir = "$major.$minor.$micro" - } - - if ($prerelease) { - if (($major -le 2) ` - -or ($major -eq 3 -and $minor -eq 1) ` - -or ($major -eq 3 -and $minor -eq 2) ` - -or ($major -eq 3 -and $minor -eq 3) ` - ) { - $dir = "$dir/prev" - } - } - - if (($major -le 2) -or ($major -le 3 -and $minor -le 4)) { - $ext = "msi" - if ($platform_suffix) { - $platform_suffix = ".$platform_suffix" - } - } else { - $ext = "exe" - if ($platform_suffix) { - $platform_suffix = "-$platform_suffix" - } - } - - $filename = "python-$python_version$platform_suffix.$ext" - $url = "$BASE_URL$dir/$filename" - $filepath = Download $filename $url - return $filepath -} - - -function InstallPython ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -eq "32") { - $platform_suffix = "" - } else { - $platform_suffix = "amd64" - } - $installer_path = DownloadPython $python_version $platform_suffix - $installer_ext = [System.IO.Path]::GetExtension($installer_path) - Write-Host "Installing $installer_path to $python_home" - $install_log = $python_home + ".log" - if ($installer_ext -eq '.msi') { - InstallPythonMSI $installer_path $python_home $install_log - } else { - InstallPythonEXE $installer_path $python_home $install_log - } - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallPythonEXE ($exepath, $python_home, $install_log) { - $install_args = "/quiet InstallAllUsers=1 TargetDir=$python_home" - RunCommand $exepath $install_args -} - - -function InstallPythonMSI ($msipath, $python_home, $install_log) { - $install_args = "/qn /log $install_log /i $msipath TARGETDIR=$python_home" - $uninstall_args = "/qn /x $msipath" - RunCommand "msiexec.exe" $install_args - if (-not(Test-Path $python_home)) { - Write-Host "Python seems to be installed else-where, reinstalling." - RunCommand "msiexec.exe" $uninstall_args - RunCommand "msiexec.exe" $install_args - } -} - -function RunCommand ($command, $command_args) { - Write-Host $command $command_args - Start-Process -FilePath $command -ArgumentList $command_args -Wait -Passthru -} - - -function InstallPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $python_path = $python_home + "\python.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $webclient = New-Object System.Net.WebClient - $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) - Write-Host "Executing:" $python_path $GET_PIP_PATH - & $python_path $GET_PIP_PATH - } else { - Write-Host "pip already installed." - } -} - - -function DownloadMiniconda ($python_version, $platform_suffix) { - if ($python_version -eq "3.4") { - $filename = "Miniconda3-3.5.5-Windows-" + $platform_suffix + ".exe" - } else { - $filename = "Miniconda-3.5.5-Windows-" + $platform_suffix + ".exe" - } - $url = $MINICONDA_URL + $filename - $filepath = Download $filename $url - return $filepath -} - - -function InstallMiniconda ($python_version, $architecture, $python_home) { - Write-Host "Installing Python" $python_version "for" $architecture "bit architecture to" $python_home - if (Test-Path $python_home) { - Write-Host $python_home "already exists, skipping." - return $false - } - if ($architecture -eq "32") { - $platform_suffix = "x86" - } else { - $platform_suffix = "x86_64" - } - $filepath = DownloadMiniconda $python_version $platform_suffix - Write-Host "Installing" $filepath "to" $python_home - $install_log = $python_home + ".log" - $args = "/S /D=$python_home" - Write-Host $filepath $args - Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru - if (Test-Path $python_home) { - Write-Host "Python $python_version ($architecture) installation complete" - } else { - Write-Host "Failed to install Python in $python_home" - Get-Content -Path $install_log - Exit 1 - } -} - - -function InstallMinicondaPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $conda_path = $python_home + "\Scripts\conda.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $args = "install --yes pip" - Write-Host $conda_path $args - Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru - } else { - Write-Host "pip already installed." - } -} - -function main () { - InstallPython $env:PYTHON_VERSION $env:PYTHON_ARCH $env:PYTHON - InstallPip $env:PYTHON -} - -main \ No newline at end of file diff --git a/.ci/run_with_env.cmd b/.ci/run_with_env.cmd deleted file mode 100644 index 5da547c499..0000000000 --- a/.ci/run_with_env.cmd +++ /dev/null @@ -1,88 +0,0 @@ -:: To build extensions for 64 bit Python 3, we need to configure environment -:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) -:: -:: To build extensions for 64 bit Python 2, we need to configure environment -:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: -:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) -:: -:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific -:: environment configurations. -:: -:: Note: this script needs to be run with the /E:ON and /V:ON flags for the -:: cmd interpreter, at least for (SDK v7.0) -:: -:: More details at: -:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows -:: http://stackoverflow.com/a/13751649/163740 -:: -:: Author: Olivier Grisel -:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ -:: -:: Notes about batch files for Python people: -:: -:: Quotes in values are literally part of the values: -:: SET FOO="bar" -:: FOO is now five characters long: " b a r " -:: If you don't want quotes, don't include them on the right-hand side. -:: -:: The CALL lines at the end of this file look redundant, but if you move them -:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y -:: case, I don't know why. -@ECHO OFF - -SET COMMAND_TO_RUN=%* -SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows -SET WIN_WDK=c:\Program Files (x86)\Windows Kits\10\Include\wdf - -:: Extract the major and minor versions, and allow for the minor version to be -:: more than 9. This requires the version number to have two dots in it. -SET MAJOR_PYTHON_VERSION=%PYTHON_VERSION:~0,1% -IF "%PYTHON_VERSION:~3,1%" == "." ( - SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,1% -) ELSE ( - SET MINOR_PYTHON_VERSION=%PYTHON_VERSION:~2,2% -) - -:: Based on the Python version, determine what SDK version to use, and whether -:: to set the SDK for 64-bit. -IF %MAJOR_PYTHON_VERSION% == 2 ( - SET WINDOWS_SDK_VERSION="v7.0" - SET SET_SDK_64=Y -) ELSE ( - IF %MAJOR_PYTHON_VERSION% == 3 ( - SET WINDOWS_SDK_VERSION="v7.1" - IF %MINOR_PYTHON_VERSION% LEQ 4 ( - SET SET_SDK_64=Y - ) ELSE ( - SET SET_SDK_64=N - IF EXIST "%WIN_WDK%" ( - :: See: https://connect.microsoft.com/VisualStudio/feedback/details/1610302/ - REN "%WIN_WDK%" 0wdf - ) - ) - ) ELSE ( - ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" - EXIT 1 - ) -) - -IF %PYTHON_ARCH% == 64 ( - IF %SET_SDK_64% == Y ( - ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture - SET DISTUTILS_USE_SDK=1 - SET MSSdk=1 - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% - "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 - ) ELSE ( - ECHO Using default MSVC build environment for 64 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 - ) -) ELSE ( - ECHO Using default MSVC build environment for 32 bit architecture - ECHO Executing: %COMMAND_TO_RUN% - call %COMMAND_TO_RUN% || EXIT 1 -) diff --git a/.ci/upload_docs.sh b/.ci/upload_docs.sh deleted file mode 100755 index 1e6f6b5ced..0000000000 --- a/.ci/upload_docs.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/bash -set -e # Exit with nonzero exit code if anything fails - -SOURCE_BRANCH="master" -TARGET_BRANCH="gh-pages" - -# Pull requests and commits to other branches shouldn't try to deploy, just build to verify -if [ "$TRAVIS_PULL_REQUEST" != "false" ] || \ - [ "$TRAVIS_BRANCH" != master -a \ - "$TRAVIS_BRANCH" != develop -a \ - "$TRAVIS_BRANCH" != travis ]; then - echo "No docs to upload." - exit 0 -fi - -if [ -z "$GH_TOKEN" ]; then - echo "Error: GH_TOKEN is undefined" - exit 1 -fi - -# Save some useful information -REPO=`git config remote.origin.url` -SHA=`git rev-parse --verify HEAD` - -# build happens to contain the "doc/html" tree that we want to push -# into the gh-pages branch. So we step into that directory, create a new repo, -# set the remote appropriately, then commit and push. -cd build -git init -git config user.name "Travis CI" -git config user.email "travis-ci" - -# Make sure 'GH_TOKEN' is set (as 'secure' variable) in .travis.yml -git remote add upstream "https://$GH_TOKEN@github.com/boostorg/python.git" -git fetch upstream -git reset upstream/gh-pages - -# Prepare version. -if [ "$TRAVIS_BRANCH" = develop -o "$TRAVIS_BRANCH" = travis ]; then - mkdir -p develop/doc/ - cp ../index.html develop/ - cp ../doc/index.html develop/doc/ - cp -a doc/html develop/doc/ - git add develop/index.html - git add develop/doc/index.html - git add -A develop/doc/html -else - cp ../index.html . - cp ../doc/index.html doc/ - git add index.html - git add doc/index.html - git add -A doc/html -fi -# Commit the new version. -git commit -m "Deploy to GitHub Pages: ${SHA}" - -# Now that we're all set up, we can push. -git push -q upstream HEAD:gh-pages diff --git a/.github/workflows/deploy-documentation.yml b/.github/workflows/deploy-documentation.yml new file mode 100644 index 0000000000..3c5ffafb70 --- /dev/null +++ b/.github/workflows/deploy-documentation.yml @@ -0,0 +1,37 @@ +name: deploy documentation + +on: [push] + +jobs: + deploy: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v5 + - name: setup + run: | + sudo apt-get update + sudo apt-get install \ + libboost-tools-dev \ + python3 \ + python3-numpy \ + python3-sphinx \ + xsltproc \ + docbook-xsl + sudo python3 -m pip install --upgrade pip + sudo python3 -m pip install faber + - name: build + run: | + sed -e "s/\$PYTHON/python3/g" .ci/faber > ~/.faber + faber --builddir=build doc.html + if [ "${GITHUB_REF##*/}" == master ]; then + echo "destination_dir=doc/html" >> $GITHUB_ENV + else + echo "destination_dir=doc/develop/html" >> $GITHUB_ENV + fi + - name: deploy + uses: peaceiris/actions-gh-pages@v4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: build/doc/html + destination_dir: ${{ env.destination_dir }} + keep_files: true diff --git a/.github/workflows/test-osx.yml b/.github/workflows/test-osx.yml new file mode 100644 index 0000000000..b88b43e5dd --- /dev/null +++ b/.github/workflows/test-osx.yml @@ -0,0 +1,50 @@ +name: Test OSX + +on: [push, pull_request] + +jobs: + build: + runs-on: macOS-latest + + strategy: + fail-fast: false + matrix: + python-version: [3.8.10] + cxx: [clang++] + std: [c++11, c++14] # TODO: c++17 is failing ! + + steps: + - uses: actions/checkout@v5 + - name: setup python + uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + - name: setup prerequisites + run: | + brew install boost + python -m pip install --upgrade pip + python -m pip install setuptools faber + - name: build + run: | + python --version + ${{ matrix.cxx }} --version + brew info boost + faber -v + sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber + faber \ + --with-boost-include=$(brew --prefix boost)/include \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`sysctl -n hw.ncpu` + - name: test + run: | + faber \ + --with-boost-include=$(brew --prefix boost)/include \ + --builddir=build\ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`sysctl -n hw.ncpu` \ + test.report diff --git a/.github/workflows/test-ubuntu.yml b/.github/workflows/test-ubuntu.yml new file mode 100644 index 0000000000..6f94c2d186 --- /dev/null +++ b/.github/workflows/test-ubuntu.yml @@ -0,0 +1,57 @@ +name: Test Ubuntu + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + python: [python, python3] + cxx: [g++, clang++] + std: [c++11, c++14, c++17] + include: + # Add the appropriate docker image for each compiler. + # The images from teeks99/boost-python-test already have boost::python + # pre-reqs installed, see: + # https://github.com/teeks99/boost-python-test-docker + - cxx: clang++ + docker-img: teeks99/boost-python-test:clang-21_1.89.0 + - cxx: g++ + docker-img: teeks99/boost-python-test:gcc-15_1.89.0 + + container: + image: ${{ matrix.docker-img }} + + steps: + - uses: actions/checkout@v5 + + - name: setup prerequisites + run: | + # Warning: this is not necessarily the same Python version as the one configured above ! + python3 -m pip install -U faber --break-system-packages + - name: build + run: | + ${{ matrix.python }} --version + ${{ matrix.cxx }} --version + faber -v + sed -e "s/\$PYTHON/${{ matrix.python }}/g" .ci/faber > ~/.faber + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`nproc` + - name: test + run: | + faber \ + --with-boost-include=${BOOST_PY_DEPS} \ + --builddir=build \ + cxx.name=${{ matrix.cxx }} \ + cxxflags=-std=${{ matrix.std }} \ + cppflags=-std=${{ matrix.std }} \ + -j`nproc` \ + test.report diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml new file mode 100644 index 0000000000..576e1f4415 --- /dev/null +++ b/.github/workflows/test-windows.yml @@ -0,0 +1,49 @@ +name: Test Windows + +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + python-version: [3.7] + + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-python@v6 + with: + python-version: ${{ matrix.python-version }} + - uses: microsoft/setup-msbuild@v2 + - name: setup boost prerequisites + uses: lukka/run-vcpkg@v6 + with: + vcpkgGitCommitId: '88b1071e39f13b632644d9d953738d345a4ac055' + vcpkgDirectory: '${{ runner.workspace }}/vcpkg' + vcpkgTriplet: x64-windows + vcpkgArguments: > + boost-config + boost-core + boost-function + boost-graph + boost-iterator + boost-lexical-cast + boost-mpl + boost-preprocessor + boost-smart-ptr + boost-static-assert + boost-align + - name: setup faber + run: | + python -m pip install --upgrade pip + python -m pip install setuptools faber numpy + faber --info=tools cxx + - name: build + shell: cmd + run: | + faber --builddir=build cxx.name=msvc --log=commands --log=output --with-boost-include=${{ runner.workspace }}\vcpkg\installed\x64-windows\include -j4 + - name: test + shell: cmd + run: | + faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}\vcpkg\installed\x64-windows\include -j4 test.report diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 657386bb0f..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,117 +0,0 @@ -# -# Copyright (c) 2016 Stefan Seefeld -# All rights reserved. -# -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -dist: bionic - -language: cpp - -env: - global: - - secure: BRNUkxN3p8f+uYKWC3Hr0VPqZA0PxbWr1DJlcI4hbiZtzKhMCWjDmd9UW9CzzexqeOxpd+9s0G87qvOur+wMSVxugDxtTesZrh1czXHeSVxgQrYD783XJtQJ9aYypbChkiboRD6Xpmbq7itwMuHBJMFtCuDxMynpU1jWwkyTf2Y= - -jobs: - include: - - os: linux - env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++98 - - os: linux - env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++11 - - os: linux - env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++98 - - os: linux - env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11 - - os: linux - env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 - - os: linux - env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 - - os: linux - env: CXX=g++ PYTHON=pypy3 CXXFLAGS=-std=c++11 - - os: osx - env: CXX=clang++ PYTHON=python CXXFLAGS=-std=c++11 - - env: PYTHON=python DOC=1 - allow_failures: - - os: linux - env: CXX=g++ PYTHON=pypy3 CXXFLAGS=-std=c++11 - - os: osx - -addons: - apt: - sources: - - ubuntu-toolchain-r-test - - pypy - packages: - - gcc - - g++ - - clang - - pypy3-dev - - python3-pip - - python-numpy - - python-sphinx - - python3-dev - - python3-numpy - - libboost-all-dev - - xsltproc - - docbook-xsl - - python-docutils - - -cache: - directories: - - $HOME/Boost - -install: - # Install our own version of Boost (the subset we need) as the system version is - # too old (for C++11 support). - - | - if [ ! -d $HOME/Boost/tools/boostbook ]; then - echo "rebuilding Boost prerequisites." - wget https://sourceforge.net/projects/boost/files/boost/1.66.0/boost_1_66_0.tar.gz/download - tar xf download - pushd boost_1_66_0 - ./bootstrap.sh - ./b2 tools/bcp - mkdir -p $HOME/Boost - # Install Boost.Python prerequisites, but not Boost.Python itself. - dist/bin/bcp python tools/boostbook tools/quickbook $HOME/Boost &> /dev/null - rm -rf $HOME/Boost/boost/python* - popd - else - echo "using cached Boost prerequisites." - fi - # Install Faber, the build tool. - python3 -m pip install setuptools - python3 -m pip install faber - #date=2020-08-01 - #wget https://github.com/stefanseefeld/faber/archive/snapshot/$date.tar.gz - #tar xf $date.tar.gz - #pushd faber-snapshot-$date - #sudo python3 setup.py install - #popd - -before_script: -- sed -e "s/\$PYTHON/$PYTHON/g" .ci/faber > ~/.faber -- $PYTHON --version -- faber -h -- ls -l $HOME/Boost - -script: -- | - if [ "$DOC" ]; then - BOOST_ROOT=$HOME/Boost faber --builddir=build doc.html - else - faber --with-boost-include=$HOME/Boost --builddir=build test.report cxx.name=$CXX cxxflags=$CXXFLAGS -j8 - fi - -after_success: -# Upload docs only when building upstream. -- | - if [ "$DOC" -a \ - "$TRAVIS_REPO_SLUG" = "boostorg/python" -a \ - "$TRAVIS_PULL_REQUEST" = "false" ]; then - export GH_TOKEN - .ci/upload_docs.sh - fi diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000..299ef84e9c --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,176 @@ +# Copyright 2020, 2021 Peter Dimov +# Distributed under the Boost Software License, Version 1.0. +# https://www.boost.org/LICENSE_1_0.txt + +cmake_minimum_required(VERSION 3.14...3.20) + +project(boost_python VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) + +find_package(Python REQUIRED COMPONENTS Development OPTIONAL_COMPONENTS NumPy) + +if(Python_NumPy_FOUND) + message(STATUS "Boost.Python: using Python ${Python_VERSION} with NumPy at ${Python_NumPy_INCLUDE_DIRS}") +else() + message(STATUS "Boost.Python: using Python ${Python_VERSION} without NumPy") +endif() + +# boost_pythonXY + +set(_pyver ${Python_VERSION_MAJOR}${Python_VERSION_MINOR}) +set(_boost_python boost_python${_pyver}) + +add_library(${_boost_python} + src/dict.cpp + src/errors.cpp + src/exec.cpp + src/import.cpp + src/list.cpp + src/long.cpp + src/module.cpp + src/object_operators.cpp + src/object_protocol.cpp + src/slice.cpp + src/str.cpp + src/tuple.cpp + src/wrapper.cpp + src/converter/from_python.cpp + src/converter/registry.cpp + src/converter/type_id.cpp + src/converter/builtin_converters.cpp + src/converter/arg_to_python_base.cpp + src/object/enum.cpp + src/object/class.cpp + src/object/function.cpp + src/object/inheritance.cpp + src/object/life_support.cpp + src/object/pickle_support.cpp + src/object/iterator.cpp + src/object/stl_iterator.cpp + src/object_protocol.cpp + src/object_operators.cpp + src/object/function_doc_signature.cpp +) + +add_library(Boost::python${_pyver} ALIAS ${_boost_python}) + +target_include_directories(${_boost_python} PUBLIC include) + +target_link_libraries(${_boost_python} + PUBLIC + Boost::align + Boost::bind + Boost::config + Boost::conversion + Boost::core + Boost::detail + Boost::foreach + Boost::function + Boost::iterator + Boost::lexical_cast + Boost::mpl + Boost::numeric_conversion + Boost::preprocessor + Boost::smart_ptr + Boost::static_assert + Boost::tuple + Boost::type_traits + Boost::utility + + Python::Module + + PRIVATE + Boost::graph + Boost::integer + Boost::property_map +) + +target_compile_definitions(${_boost_python} + PUBLIC BOOST_PYTHON_NO_LIB + PRIVATE BOOST_PYTHON_SOURCE +) + +if(BUILD_SHARED_LIBS) + target_compile_definitions(${_boost_python} PUBLIC BOOST_PYTHON_DYN_LINK) +else() + target_compile_definitions(${_boost_python} PUBLIC BOOST_PYTHON_STATIC_LINK BOOST_PYTHON_STATIC_LIB) +endif() + +# Boost::python alias + +add_library(boost_python INTERFACE) +add_library(Boost::python ALIAS boost_python) +target_link_libraries(boost_python INTERFACE Boost::python${_pyver}) + +# Installation + +if(BOOST_SUPERPROJECT_VERSION AND NOT CMAKE_VERSION VERSION_LESS 3.13) + boost_install(TARGETS ${_boost_python} boost_python VERSION ${BOOST_SUPERPROJECT_VERSION} HEADER_DIRECTORY include) +endif() + +if(Python_NumPy_FOUND) + +# boost_numpyXY + +set(_boost_numpy boost_numpy${_pyver}) + +add_library(${_boost_numpy} + src/numpy/dtype.cpp + src/numpy/matrix.cpp + src/numpy/ndarray.cpp + src/numpy/numpy.cpp + src/numpy/scalars.cpp + src/numpy/ufunc.cpp +) + +add_library(Boost::numpy${_pyver} ALIAS ${_boost_numpy}) + +target_include_directories(${_boost_numpy} PUBLIC include) + +target_link_libraries(${_boost_numpy} + PUBLIC + Boost::config + Boost::core + Boost::detail + Boost::mpl + Boost::python + Boost::smart_ptr + + Python::NumPy +) + +target_compile_definitions(${_boost_numpy} + PUBLIC BOOST_NUMPY_NO_LIB + PRIVATE BOOST_NUMPY_SOURCE +) + +if(BUILD_SHARED_LIBS) + target_compile_definitions(${_boost_numpy} PUBLIC BOOST_NUMPY_DYN_LINK) +else() + target_compile_definitions(${_boost_numpy} PUBLIC BOOST_NUMPY_STATIC_LINK BOOST_NUMPY_STATIC_LIB) +endif() + +# Boost::numpy alias + +add_library(boost_numpy INTERFACE) +add_library(Boost::numpy ALIAS boost_numpy) +target_link_libraries(boost_numpy INTERFACE Boost::numpy${_pyver}) + +# Installation + +if(BOOST_SUPERPROJECT_VERSION AND NOT CMAKE_VERSION VERSION_LESS 3.13) + boost_install(TARGETS ${_boost_numpy} boost_numpy VERSION ${BOOST_SUPERPROJECT_VERSION}) +endif() + +endif() + +unset(_pyver) +unset(_boost_python) +unset(_boost_numpy) + +# Testing + +if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") + + add_subdirectory(test) + +endif() diff --git a/README.md b/README.md index 7646d3a877..f57b97505a 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,7 @@ See the [Boost.Python](http://boostorg.github.io/python) documentation for detai **Hint :** Check out the [development version](http://boostorg.github.io/python/develop) of the documentation to see work in progress. -# Building [![Build Status](https://travis-ci.org/boostorg/python.svg?branch=develop)](https://travis-ci.org/boostorg/python) [![Build status](https://ci.appveyor.com/api/projects/status/cgx9xma6v3gjav92/branch/develop?svg=true)](https://ci.appveyor.com/project/stefanseefeld/python/branch/develop) - +# Building ![Test Ubuntu](https://github.com/boostorg/python/workflows/Test%20Ubuntu/badge.svg) ![Test OSX](https://github.com/boostorg/python/workflows/Test%20OSX/badge.svg) ![Test Windows](https://github.com/boostorg/python/workflows/Test%20Windows/badge.svg) While Boost.Python is part of the Boost C++ Libraries super-project, and thus can be compiled as part of Boost, it can also be compiled and installed stand-alone, i.e. against a pre-installed Boost package. diff --git a/build.jam b/build.jam new file mode 100644 index 0000000000..e9eb1a11a2 --- /dev/null +++ b/build.jam @@ -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 + ; + +explicit + [ alias boost_python : build//boost_python ] + [ alias boost_numpy : build//boost_numpy ] + [ alias all : boost_python boost_numpy test ] + ; + +call-if : boost-library python + : install boost_python boost_numpy + ; + diff --git a/build/Jamfile b/build/Jamfile index dbc9fb2036..c8f9859c64 100644 --- a/build/Jamfile +++ b/build/Jamfile @@ -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 + : common-requirements $(boost_dependencies) + : requirements $(boost_dependencies_private) ; rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } } rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } } local rule eq ( a : b ) { if $(a) = $(b) { return 1 ; } } +rule tag ( name : type ? : property-set ) +{ + if python-tag in [ RULENAMES $(__name__) ] + { + return [ $(__name__).python-tag $(name) : $(type) : $(property-set) ] ; + } +} + +if [ python.configured ] +{ + lib boost_python : # sources list.cpp @@ -92,8 +112,9 @@ lib boost_python [ unless [ python.configured ] : no ] config-warning on:BOOST_DEBUG_PYTHON + -@%boostcpp.tag -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @python-tag + @tag @python.require-py : # default build @@ -101,8 +122,20 @@ lib boost_python : # usage requirements static:BOOST_PYTHON_STATIC_LIB on:BOOST_DEBUG_PYTHON + BOOST_PYTHON_NO_LIB ; +} +else +{ + +alias boost_python : config-warning ; + +} + +if [ python.configured ] && [ python.numpy ] +{ + numpy-include = [ python.numpy-include ] ; lib boost_numpy : # sources @@ -117,11 +150,12 @@ lib boost_numpy BOOST_NUMPY_SOURCE [ cond [ python.numpy ] : /python//python_for_extensions ] [ unless [ python.numpy ] : no ] - $(numpy-include) + /python//numpy boost_python on:BOOST_DEBUG_PYTHON + -@%boostcpp.tag -@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag - @python-tag + @tag @python.require-py : # default build @@ -129,39 +163,13 @@ lib boost_numpy : # usage requirements static:BOOST_NUMPY_STATIC_LIB on:BOOST_DEBUG_PYTHON + 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 { -# When Python isn't configured, the above `boost-install` is not executed, -# so we create empty `stage` and `install` targets that do nothing but issue -# a warning message unless `--without-python` is given - -alias stage : config-warning ; -explicit stage ; - -alias install : config-warning ; -explicit install ; +alias boost_numpy : config-warning ; } diff --git a/doc/numpy/_static/boost.css b/doc/numpy/_static/boost.css index 28f8935991..36c1efd082 100644 --- a/doc/numpy/_static/boost.css +++ b/doc/numpy/_static/boost.css @@ -714,3 +714,23 @@ span.purple { color: purple; } span.gold { color: gold; } span.silver { color: silver; } /* lighter gray */ span.gray { color: #808080; } /* light gray */ + +/* 2022 fix */ + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + diff --git a/doc/numpy/_templates/layout.html b/doc/numpy/_templates/layout.html index 1aa68f0ea1..69e1a868c0 100644 --- a/doc/numpy/_templates/layout.html +++ b/doc/numpy/_templates/layout.html @@ -49,6 +49,9 @@ {%- for scriptfile in script_files %} {%- endfor %} + + + {%- if use_opensearch %}

C++ Boost

+ alt="C++ Boost" src="{{ pathto('_static/bpl.png', 1) }}" border="0"> diff --git a/doc/numpy/conf.py b/doc/numpy/conf.py index 2f5d5e8146..23ab678d3a 100644 --- a/doc/numpy/conf.py +++ b/doc/numpy/conf.py @@ -40,8 +40,8 @@ master_doc = 'index' # General information about the project. -project = u'Boost.Python NumPy extension' -copyright = u'2011, Stefan Seefeld' +project = 'Boost.Python NumPy extension' +copyright = '2011, Stefan Seefeld' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -181,8 +181,8 @@ # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('index', 'BoostPythonNumPy.tex', u'Boost.Python NumPy Documentation', - u'Stefan Seefeld', 'manual'), + ('index', 'BoostPythonNumPy.tex', 'Boost.Python NumPy Documentation', + 'Stefan Seefeld', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -214,6 +214,6 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'boostnumpy', u'Boost.Python NumPy Documentation', - [u'Stefan Seefeld'], 1) + ('index', 'boostnumpy', 'Boost.Python NumPy Documentation', + ['Stefan Seefeld'], 1) ] diff --git a/doc/numpy/tutorial/dtype.rst b/doc/numpy/tutorial/dtype.rst index 557e72ba2d..9bea646a65 100644 --- a/doc/numpy/tutorial/dtype.rst +++ b/doc/numpy/tutorial/dtype.rst @@ -48,7 +48,7 @@ Next, create a list, and add this tuple to the list. Then use the list to create list_for_dtype.append(for_custom_dtype) ; np::dtype custom_dtype = np::dtype(list_for_dtype) ; -We are now ready to create an ndarray with dimensions specified by \*shape\* and of custom dtpye :: +We are now ready to create an ndarray with dimensions specified by \*shape\* and of custom dtype :: np::ndarray new_array = np::zeros(shape,custom_dtype); } diff --git a/doc/reference/call_method.qbk b/doc/reference/call_method.qbk index 926763cebc..fcf68667d0 100644 --- a/doc/reference/call_method.qbk +++ b/doc/reference/call_method.qbk @@ -20,6 +20,8 @@ C++ Module Definition `` #include #include +#include +#include #include #include @@ -28,7 +30,7 @@ class Base { public: virtual char const* class_name() const { return "Base"; } - virtual ~Base(); + virtual ~Base() {}; }; bool is_base(Base* b) @@ -56,7 +58,7 @@ BOOST_PYTHON_MODULE(my_module) { def("is_base", is_base); - class_("Base") + class_("Base") .def("class_name", &Base_callback::Base_name) ; diff --git a/doc/tutorial.qbk b/doc/tutorial.qbk index d7c0cfa93e..197470013e 100644 --- a/doc/tutorial.qbk +++ b/doc/tutorial.qbk @@ -117,7 +117,7 @@ platforms. The complete list of Bjam executables can be found [h2 Let's Jam!] __jam__ -[@../../../../example/tutorial/Jamroot Here] is our minimalist Jamroot +[@../example/Jamroot Here] is our minimalist Jamroot file. Simply copy the file and tweak [^use-project boost] to where your boost root directory is and you're OK. diff --git a/example/README.md b/example/README.md index b090cbe1e3..af03f20ba8 100644 --- a/example/README.md +++ b/example/README.md @@ -3,7 +3,7 @@ # Examples This directory contains various examples using Boost.Python. -You may compile these using the `bjam` command either in this directory +You may compile these using the `b2` command either in this directory or in any of the subdirectories. You may need to adjust the paths in the Jamroot file if Boost.Python is not installed in a default location. diff --git a/example/numpy/demo_gaussian.py b/example/numpy/demo_gaussian.py index 0b1c78995e..08bb58b82a 100644 --- a/example/numpy/demo_gaussian.py +++ b/example/numpy/demo_gaussian.py @@ -3,6 +3,7 @@ # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) +from __future__ import print_function import numpy import gaussian @@ -19,19 +20,19 @@ z = g(x, y) s = z.sum() * (r[1] - r[0])**2 -print "sum (should be ~ 1):", s +print("sum (should be ~ 1):", s) xc = (z * x).sum() / z.sum() -print "x centroid (should be ~ %f): %f" % (mu[0], xc) +print("x centroid (should be ~ %f): %f" % (mu[0], xc)) yc = (z * y).sum() / z.sum() -print "y centroid (should be ~ %f): %f" % (mu[1], yc) +print("y centroid (should be ~ %f): %f" % (mu[1], yc)) xx = (z * (x - xc)**2).sum() / z.sum() -print "xx moment (should be ~ %f): %f" % (sigma[0,0], xx) +print("xx moment (should be ~ %f): %f" % (sigma[0,0], xx)) yy = (z * (y - yc)**2).sum() / z.sum() -print "yy moment (should be ~ %f): %f" % (sigma[1,1], yy) +print("yy moment (should be ~ %f): %f" % (sigma[1,1], yy)) xy = 0.5 * (z * (x - xc) * (y - yc)).sum() / z.sum() -print "xy moment (should be ~ %f): %f" % (sigma[0,1], xy) +print("xy moment (should be ~ %f): %f" % (sigma[0,1], xy)) diff --git a/example/quickstart/script.py b/example/quickstart/script.py index c3e034ba84..f360cef2d2 100644 --- a/example/quickstart/script.py +++ b/example/quickstart/script.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # Copyright Stefan Seefeld 2006. Distributed under the Boost # Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/example/quickstart/test_extending.py b/example/quickstart/test_extending.py index 938c7b9047..035ca96134 100644 --- a/example/quickstart/test_extending.py +++ b/example/quickstart/test_extending.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # Copyright Ralf W. Grosse-Kunstleve 2006. Distributed under the Boost # Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/example/tutorial/hello.py b/example/tutorial/hello.py index 31f75565df..7888b2e0fd 100755 --- a/example/tutorial/hello.py +++ b/example/tutorial/hello.py @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python3 # Copyright Joel de Guzman 2002-2007. Distributed under the Boost # Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt # or copy at http://www.boost.org/LICENSE_1_0.txt) diff --git a/fabscript b/fabscript index 8188779fd3..5a50615fc8 100644 --- a/fabscript +++ b/fabscript @@ -16,6 +16,7 @@ from faber.config.try_run import try_run features += include('include') features += define('BOOST_ALL_NO_LIB') # disable auto-linking +features += define('BOOST_NO_AUTO_PTR') boost_include = options.get_with('boost-include') if boost_include: features += include(boost_include) diff --git a/include/boost/python/call_method.hpp b/include/boost/python/call_method.hpp index 424077eab4..2f360791d7 100644 --- a/include/boost/python/call_method.hpp +++ b/include/boost/python/call_method.hpp @@ -59,7 +59,7 @@ call_method(PyObject* self, char const* name ) { PyObject* const result = - PyEval_CallMethod( + PyObject_CallMethod( self , const_cast(name) , const_cast("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")") diff --git a/include/boost/python/class.hpp b/include/boost/python/class.hpp index 77f915ba0a..0f1c0fdc1a 100644 --- a/include/boost/python/class.hpp +++ b/include/boost/python/class.hpp @@ -372,10 +372,11 @@ class class_ : public objects::class_base { typedef typename api::is_object_operators::type is_obj_or_proxy; - return this->make_fn_impl( + return objects::add_doc( + this->make_fn_impl( detail::unwrap_wrapper((W*)0) , f, is_obj_or_proxy(), (char*)0, detail::is_data_member_pointer() - ); + ), NULL); } template @@ -383,10 +384,11 @@ class class_ : public objects::class_base { typedef typename api::is_object_operators::type is_obj_or_proxy; - return this->make_fn_impl( + return objects::add_doc( + this->make_fn_impl( detail::unwrap_wrapper((W*)0) , f, is_obj_or_proxy(), (int*)0, detail::is_data_member_pointer() - ); + ), NULL); } template diff --git a/include/boost/python/converter/obj_mgr_arg_from_python.hpp b/include/boost/python/converter/obj_mgr_arg_from_python.hpp index cd4e1e0ea8..5132804082 100644 --- a/include/boost/python/converter/obj_mgr_arg_from_python.hpp +++ b/include/boost/python/converter/obj_mgr_arg_from_python.hpp @@ -81,9 +81,9 @@ inline object_manager_ref_arg_from_python::object_manager_ref_arg_from_pyth # if defined(__EDG_VERSION__) && __EDG_VERSION__ <= 243 // needed for warning suppression python::detail::borrowed_reference x_ = python::detail::borrowed_reference(x); - python::detail::construct_referent(&m_result.bytes, x_); + python::detail::construct_referent(m_result.bytes, x_); # else - python::detail::construct_referent(&m_result.bytes, (python::detail::borrowed_reference)x); + python::detail::construct_referent(m_result.bytes, (python::detail::borrowed_reference)x); # endif } diff --git a/include/boost/python/converter/pytype_function.hpp b/include/boost/python/converter/pytype_function.hpp index 8e0a4e7995..d072b55fb3 100644 --- a/include/boost/python/converter/pytype_function.hpp +++ b/include/boost/python/converter/pytype_function.hpp @@ -9,7 +9,7 @@ # include # include # include - +# include namespace boost { namespace python { @@ -46,6 +46,12 @@ inline python::type_info unwind_type_id_(boost::type* = 0, mpl::false_ * =0) return boost::python::detail::unwind_type (); } +template +inline python::type_info unwind_type_id_(boost::type >* = 0, mpl::false_ * =0) +{ + return boost::python::detail::unwind_type (); +} + inline python::type_info unwind_type_id_(boost::type* = 0, mpl::true_* =0) { return type_id(); diff --git a/include/boost/python/converter/rvalue_from_python_data.hpp b/include/boost/python/converter/rvalue_from_python_data.hpp index acb38f8498..d728681b3e 100644 --- a/include/boost/python/converter/rvalue_from_python_data.hpp +++ b/include/boost/python/converter/rvalue_from_python_data.hpp @@ -9,6 +9,7 @@ # include # include # include +# include # include # include @@ -132,7 +133,13 @@ template inline rvalue_from_python_data::~rvalue_from_python_data() { if (this->stage1.convertible == this->storage.bytes) - python::detail::destroy_referent(this->storage.bytes); + { + size_t allocated = sizeof(this->storage); + void *ptr = this->storage.bytes; + void *aligned_storage = + ::boost::alignment::align(boost::python::detail::alignment_of::value, 0, ptr, allocated); + python::detail::destroy_referent(aligned_storage); + } } }}} // namespace boost::python::converter diff --git a/include/boost/python/converter/shared_ptr_from_python.hpp b/include/boost/python/converter/shared_ptr_from_python.hpp index bb2ae863ff..b5c62ba940 100644 --- a/include/boost/python/converter/shared_ptr_from_python.hpp +++ b/include/boost/python/converter/shared_ptr_from_python.hpp @@ -49,13 +49,17 @@ struct shared_ptr_from_python new (storage) SP(); else { - SP hold_convertible_ref_count( - (void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); - // use aliasing constructor - new (storage) SP(hold_convertible_ref_count, - static_cast(data->convertible)); + void *const storage = ((converter::rvalue_from_python_storage >*)data)->storage.bytes; + // Deal with the "None" case. + if (data->convertible == source) + new (storage) SP(); + else + { + SP hold_convertible_ref_count((void*)0, shared_ptr_deleter(handle<>(borrowed(source))) ); + // use aliasing constructor + new (storage) SP(hold_convertible_ref_count, static_cast(data->convertible)); + } } - data->convertible = storage; } }; diff --git a/include/boost/python/detail/config.hpp b/include/boost/python/detail/config.hpp index 8dce9b742e..e2ac827040 100644 --- a/include/boost/python/detail/config.hpp +++ b/include/boost/python/detail/config.hpp @@ -57,9 +57,15 @@ ****************************************************************************/ // backwards compatibility: -#ifdef BOOST_PYTHON_STATIC_LIB -# define BOOST_PYTHON_STATIC_LINK -# elif !defined(BOOST_PYTHON_DYNAMIC_LIB) +#if defined(BOOST_PYTHON_STATIC_LINK) && !defined(BOOST_PYTHON_STATIC_LIB) +# define BOOST_PYTHON_STATIC_LIB +#endif + +#if defined(BOOST_PYTHON_DYNAMIC_LINK) && !defined(BOOST_PYTHON_DYNAMIC_LIB) +# define BOOST_PYTHON_DYNAMIC_LIB +#endif + +#if !defined(BOOST_PYTHON_STATIC_LIB) && !defined(BOOST_PYTHON_DYNAMIC_LIB) # define BOOST_PYTHON_DYNAMIC_LIB #endif diff --git a/include/boost/python/detail/is_auto_ptr.hpp b/include/boost/python/detail/is_auto_ptr.hpp index 3b8198b8dd..36affcd215 100644 --- a/include/boost/python/detail/is_auto_ptr.hpp +++ b/include/boost/python/detail/is_auto_ptr.hpp @@ -8,6 +8,8 @@ # ifndef BOOST_NO_AUTO_PTR # include # include +# else +# include # endif namespace boost { namespace python { namespace detail { diff --git a/include/boost/python/detail/referent_storage.hpp b/include/boost/python/detail/referent_storage.hpp index 2cddf696d5..f646d2ae1d 100644 --- a/include/boost/python/detail/referent_storage.hpp +++ b/include/boost/python/detail/referent_storage.hpp @@ -5,39 +5,21 @@ #ifndef REFERENT_STORAGE_DWA200278_HPP # define REFERENT_STORAGE_DWA200278_HPP # include +# include # include namespace boost { namespace python { namespace detail { -struct alignment_dummy; -typedef void (*function_ptr)(); -typedef int (alignment_dummy::*member_ptr); -typedef int (alignment_dummy::*member_function_ptr)(); - -# define BOOST_PYTHON_ALIGNER(T, n) \ - typename mpl::if_c< \ - sizeof(T) <= size, T, char>::type t##n - -// Storage for size bytes, aligned to all fundamental types no larger than size -template -union aligned_storage +template +struct aligned_storage { - BOOST_PYTHON_ALIGNER(char, 0); - BOOST_PYTHON_ALIGNER(short, 1); - BOOST_PYTHON_ALIGNER(int, 2); - BOOST_PYTHON_ALIGNER(long, 3); - BOOST_PYTHON_ALIGNER(float, 4); - BOOST_PYTHON_ALIGNER(double, 5); - BOOST_PYTHON_ALIGNER(long double, 6); - BOOST_PYTHON_ALIGNER(void*, 7); - BOOST_PYTHON_ALIGNER(function_ptr, 8); - BOOST_PYTHON_ALIGNER(member_ptr, 9); - BOOST_PYTHON_ALIGNER(member_function_ptr, 10); + union type + { + typename ::boost::aligned_storage::type data; char bytes[size]; + }; }; - -# undef BOOST_PYTHON_ALIGNER - + // Compute the size of T's referent. We wouldn't need this at all, // but sizeof() is broken in CodeWarriors <= 8.0 template struct referent_size; @@ -50,15 +32,12 @@ union aligned_storage std::size_t, value = sizeof(T)); }; - // A metafunction returning a POD type which can store U, where T == // U&. If T is not a reference type, returns a POD which can store T. template struct referent_storage { - typedef aligned_storage< - ::boost::python::detail::referent_size::value - > type; + typedef typename aligned_storage::value, alignment_of::value>::type type; }; }}} // namespace boost::python::detail diff --git a/include/boost/python/detail/wrap_python.hpp b/include/boost/python/detail/wrap_python.hpp index 9d5f5422a2..037e4bf2ec 100644 --- a/include/boost/python/detail/wrap_python.hpp +++ b/include/boost/python/detail/wrap_python.hpp @@ -227,7 +227,11 @@ typedef int pid_t; # define PyVarObject_HEAD_INIT(type, size) \ PyObject_HEAD_INIT(type) size, +#endif +#if PY_VERSION_HEX < 0x030900A4 +# define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0) +# define Py_SET_SIZE(obj, size) ((Py_SIZE(obj) = (size)), (void)0) #endif diff --git a/include/boost/python/exception_translator.hpp b/include/boost/python/exception_translator.hpp index 75ed0e1eec..1aa1465bdf 100644 --- a/include/boost/python/exception_translator.hpp +++ b/include/boost/python/exception_translator.hpp @@ -7,7 +7,7 @@ # include -# include +# include # include # include # include @@ -18,6 +18,7 @@ namespace boost { namespace python { template void register_exception_translator(Translate translate, boost::type* = 0) { + using namespace boost::placeholders; detail::register_exception_handler( boost::bind(detail::translate_exception(), _1, _2, translate) ); diff --git a/include/boost/python/instance_holder.hpp b/include/boost/python/instance_holder.hpp index 933f50d1a1..f4ed1e6608 100644 --- a/include/boost/python/instance_holder.hpp +++ b/include/boost/python/instance_holder.hpp @@ -38,7 +38,7 @@ struct BOOST_PYTHON_DECL instance_holder : private noncopyable // Allocate storage for an object of the given size at the given // offset in the Python instance<> object if bytes are available // there. Otherwise allocate size bytes of heap memory. - static void* allocate(PyObject*, std::size_t offset, std::size_t size); + static void* allocate(PyObject*, std::size_t offset, std::size_t size, std::size_t alignment = 1); // Deallocate storage from the heap if it was not carved out of // the given Python object by allocate(), above. diff --git a/include/boost/python/iterator.hpp b/include/boost/python/iterator.hpp index 7c06ca2320..b0ea578959 100644 --- a/include/boost/python/iterator.hpp +++ b/include/boost/python/iterator.hpp @@ -22,7 +22,7 @@ works correctly. */ # pragma warning(disable: 4180) # endif -# include +# include # include namespace boost { namespace python { @@ -40,6 +40,7 @@ namespace detail , Target&(*)() ) { + using namespace boost::placeholders; return objects::make_iterator_function( boost::protect(boost::bind(get_start, _1)) , boost::protect(boost::bind(get_finish, _1)) diff --git a/include/boost/python/make_constructor.hpp b/include/boost/python/make_constructor.hpp index 3ec9ad5f86..3769970cad 100644 --- a/include/boost/python/make_constructor.hpp +++ b/include/boost/python/make_constructor.hpp @@ -61,7 +61,8 @@ namespace detail typedef objects::pointer_holder holder; typedef objects::instance instance_t; - void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder)); + void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder), + boost::python::detail::alignment_of::value); try { #if defined(BOOST_NO_CXX11_SMART_PTR) (new (memory) holder(x))->install(this->m_self); diff --git a/include/boost/python/numpy/dtype.hpp b/include/boost/python/numpy/dtype.hpp index 4673745e57..9438d79fdc 100644 --- a/include/boost/python/numpy/dtype.hpp +++ b/include/boost/python/numpy/dtype.hpp @@ -17,6 +17,7 @@ #include #include #include +#include namespace boost { namespace python { namespace numpy { diff --git a/include/boost/python/object/add_to_namespace.hpp b/include/boost/python/object/add_to_namespace.hpp index 9f4167d6d2..e81186790a 100644 --- a/include/boost/python/object/add_to_namespace.hpp +++ b/include/boost/python/object/add_to_namespace.hpp @@ -18,6 +18,8 @@ BOOST_PYTHON_DECL void add_to_namespace( BOOST_PYTHON_DECL void add_to_namespace( object const& name_space, char const* name, object const& attribute, char const* doc); +BOOST_PYTHON_DECL object const& add_doc(object const& attribute, char const* doc); + }}} // namespace boost::python::objects #endif // ADD_TO_NAMESPACE_DWA200286_HPP diff --git a/include/boost/python/object/function.hpp b/include/boost/python/object/function.hpp index f29d344820..ec1fc3d38b 100644 --- a/include/boost/python/object/function.hpp +++ b/include/boost/python/object/function.hpp @@ -35,6 +35,8 @@ struct BOOST_PYTHON_DECL function : PyObject static void add_to_namespace( object const& name_space, char const* name, object const& attribute, char const* doc); + static object const& add_doc(object const& attribute, char const* doc); + object const& doc() const; void doc(object const& x); @@ -42,6 +44,8 @@ struct BOOST_PYTHON_DECL function : PyObject object const& get_namespace() const { return m_namespace; } + object const& get_module() const { return m_module; } + private: // helper functions object signature(bool show_return_type=false) const; object signatures(bool show_return_type=false) const; @@ -53,6 +57,7 @@ struct BOOST_PYTHON_DECL function : PyObject handle m_overloads; object m_name; object m_namespace; + object m_module; object m_doc; object m_arg_names; unsigned m_nkeyword_values; diff --git a/include/boost/python/object/function_doc_signature.hpp b/include/boost/python/object/function_doc_signature.hpp index 4f00cb385a..91c90895ca 100644 --- a/include/boost/python/object/function_doc_signature.hpp +++ b/include/boost/python/object/function_doc_signature.hpp @@ -18,13 +18,13 @@ namespace boost { namespace python { namespace objects { class function_doc_signature_generator{ - static 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 are_seq_overloads( function const *f1, function const *f2 , bool check_docs); static std::vector flatten(function const *f); static std::vector split_seq_overloads( const std::vector &funcs, bool split_on_doc_change); static str raw_function_pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); - static str parameter_string(py_function const &f, size_t n, object arg_names, bool cpp_types); + static str parameter_string(py_function const &f, size_t n, object arg_names, const object& module_name, bool cpp_types); static str pretty_signature(function const *f, size_t n_overloads, bool cpp_types = false); public: diff --git a/include/boost/python/object/instance.hpp b/include/boost/python/object/instance.hpp index 27b91a1e5f..ee4a6c5822 100644 --- a/include/boost/python/object/instance.hpp +++ b/include/boost/python/object/instance.hpp @@ -6,7 +6,7 @@ # define INSTANCE_DWA200295_HPP # include - +# include # include namespace boost { namespace python @@ -28,7 +28,7 @@ struct instance typedef typename boost::python::detail::type_with_alignment< boost::python::detail::alignment_of::value >::type align_t; - + union { align_t align; @@ -41,9 +41,10 @@ struct additional_instance_size { typedef instance instance_data; typedef instance instance_char; - BOOST_STATIC_CONSTANT( - std::size_t, value = sizeof(instance_data) - - BOOST_PYTHON_OFFSETOF(instance_char,storage)); + BOOST_STATIC_CONSTANT(std::size_t, + value = sizeof(instance_data) - + BOOST_PYTHON_OFFSETOF(instance_char,storage) + + boost::python::detail::alignment_of::value); }; }}} // namespace boost::python::object diff --git a/include/boost/python/object/make_holder.hpp b/include/boost/python/object/make_holder.hpp index 0d54dd9f66..735e5395ca 100644 --- a/include/boost/python/object/make_holder.hpp +++ b/include/boost/python/object/make_holder.hpp @@ -89,8 +89,9 @@ struct make_holder BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(1, N, t, a)) { typedef instance instance_t; - - void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder)); + + void* memory = Holder::allocate(p, offsetof(instance_t, storage), sizeof(Holder), + boost::python::detail::alignment_of::value); try { (new (memory) Holder( p BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_DO_FORWARD_ARG, nil)))->install(p); diff --git a/include/boost/python/object/make_instance.hpp b/include/boost/python/object/make_instance.hpp index 31ec08f7c3..713fdc5ecd 100644 --- a/include/boost/python/object/make_instance.hpp +++ b/include/boost/python/object/make_instance.hpp @@ -43,11 +43,14 @@ struct make_instance_impl // construct the new C++ object and install the pointer // in the Python object. - Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result); + Holder *holder =Derived::construct(instance->storage.bytes, (PyObject*)instance, x); + holder->install(raw_result); // Note the position of the internally-stored Holder, // for the sake of destruction - Py_SIZE(instance) = offsetof(instance_t, storage); + const size_t offset = reinterpret_cast(holder) - + reinterpret_cast(instance->storage.bytes) + offsetof(instance_t, storage); + Py_SET_SIZE(instance, offset); // Release ownership of the python object protect.cancel(); @@ -69,7 +72,10 @@ struct make_instance static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper x) { - return new (storage) Holder(instance, x); + size_t allocated = objects::additional_instance_size::value; + void* aligned_storage = ::boost::alignment::align(boost::python::detail::alignment_of::value, + sizeof(Holder), storage, allocated); + return new (aligned_storage) Holder(instance, x); } }; diff --git a/include/boost/python/object_operators.hpp b/include/boost/python/object_operators.hpp index d436bb0144..45d6d028cc 100644 --- a/include/boost/python/object_operators.hpp +++ b/include/boost/python/object_operators.hpp @@ -9,7 +9,7 @@ # include # include -# include +# include # include # include @@ -40,7 +40,7 @@ struct is_object_operators # if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_IS_CONVERTIBLE) template struct enable_binary - : boost::iterators::enable_if, T> + : boost::enable_if_::value, T> {}; # define BOOST_PYTHON_BINARY_RETURN(T) typename enable_binary::type # else diff --git a/include/boost/python/pure_virtual.hpp b/include/boost/python/pure_virtual.hpp index 58e9aedef1..f3b298de2c 100644 --- a/include/boost/python/pure_virtual.hpp +++ b/include/boost/python/pure_virtual.hpp @@ -96,6 +96,7 @@ namespace detail , make_function( detail::nullary_function_adaptor(pure_virtual_called) , default_call_policies() + , options.keywords() , detail::error_signature(detail::get_signature(m_pmf)) ) ); diff --git a/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp b/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp index eb8b81c0a3..d470e32d77 100644 --- a/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp +++ b/include/boost/python/suite/indexing/detail/indexing_suite_detail.hpp @@ -216,7 +216,13 @@ namespace boost { namespace python { namespace detail { { for (const_iterator i = proxies.begin(); i != proxies.end(); ++i) { - if ((*i)->ob_refcnt <= 0) + if ( +#if PY_VERSION_HEX < 0x03090000 + (*i)->ob_refcnt +#else + Py_REFCNT(*i) +#endif + <= 0) { PyErr_SetString(PyExc_RuntimeError, "Invariant: Proxy vector in an inconsistent state"); diff --git a/meta/libraries.json b/meta/libraries.json index e2f2a05472..80f20f846c 100644 --- a/meta/libraries.json +++ b/meta/libraries.json @@ -10,5 +10,6 @@ ], "maintainers": [ "Stefan Seefeld " - ] + ], + "cxxstd": "03" } diff --git a/src/converter/from_python.cpp b/src/converter/from_python.cpp index 9678be1cb6..f3989ba77f 100644 --- a/src/converter/from_python.cpp +++ b/src/converter/from_python.cpp @@ -222,7 +222,13 @@ namespace , char const* ref_type) { handle<> holder(source); - if (source->ob_refcnt <= 1) + if ( +#if PY_VERSION_HEX < 0x03090000 + source->ob_refcnt +#else + Py_REFCNT(source) +#endif + <= 1) { handle<> msg( #if PY_VERSION_HEX >= 0x3000000 diff --git a/src/exec.cpp b/src/exec.cpp index b2eabe59f6..7488da1f6d 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -109,14 +109,14 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l PyObject *fo = Py_BuildValue("s", f); PyObject *fb = Py_None; PyUnicode_FSConverter(fo, &fb); - f = PyBytes_AsString(fb); - FILE *fs = fopen(f, "r"); + char *f_as_uft = PyBytes_AsString(fb); + FILE *fs = fopen(f_as_uft, "r"); Py_DECREF(fo); Py_DECREF(fb); #elif PY_VERSION_HEX >= 0x03000000 // Let python open the file to avoid potential binary incompatibilities. PyObject *fo = Py_BuildValue("s", f); - FILE *fs = _Py_fopen(fo, "r"); // Private CPython API + FILE *fs = fopen(fo, "r"); Py_DECREF(fo); #else // Let python open the file to avoid potential binary incompatibilities. @@ -129,6 +129,7 @@ object BOOST_PYTHON_DECL exec_file(char const *filename, object global, object l f, Py_file_input, global.ptr(), local.ptr()); + fclose(fs); if (!result) throw_error_already_set(); return object(detail::new_reference(result)); } diff --git a/src/module.cpp b/src/module.cpp index 9628481996..57675fa2df 100644 --- a/src/module.cpp +++ b/src/module.cpp @@ -21,7 +21,7 @@ namespace object m_obj(((borrowed_reference_t*)m)); scope current_module(m_obj); - handle_exception(init_function); + if (handle_exception(init_function)) return NULL; } return m; diff --git a/src/numpy/dtype.cpp b/src/numpy/dtype.cpp index 88a20a27b5..1ce8c6ec32 100644 --- a/src/numpy/dtype.cpp +++ b/src/numpy/dtype.cpp @@ -98,37 +98,18 @@ python::detail::new_reference dtype::convert(object const & arg, bool align) return python::detail::new_reference(reinterpret_cast(obj)); } -int dtype::get_itemsize() const { return reinterpret_cast(ptr())->elsize;} - -bool equivalent(dtype const & a, dtype const & b) { - // On Windows x64, the behaviour described on - // http://docs.scipy.org/doc/numpy/reference/c-api.array.html for - // PyArray_EquivTypes unfortunately does not extend as expected: - // "For example, on 32-bit platforms, NPY_LONG and NPY_INT are equivalent". - // This should also hold for 64-bit platforms (and does on Linux), but not - // on Windows. Implement an alternative: -#ifdef _MSC_VER - if (sizeof(long) == sizeof(int) && - // Manually take care of the type equivalence. - ((a == dtype::get_builtin() || a == dtype::get_builtin()) && - (b == dtype::get_builtin() || b == dtype::get_builtin()) || - (a == dtype::get_builtin() || a == dtype::get_builtin()) && - (b == dtype::get_builtin() || b == dtype::get_builtin()))) { - return true; - } else { - return PyArray_EquivTypes( - reinterpret_cast(a.ptr()), - reinterpret_cast(b.ptr()) - ); - } +int dtype::get_itemsize() const { +#if NPY_ABI_VERSION < 0x02000000 + return reinterpret_cast(ptr())->elsize; #else - return PyArray_EquivTypes( - reinterpret_cast(a.ptr()), - reinterpret_cast(b.ptr()) - ); + return PyDataType_ELSIZE(reinterpret_cast(ptr())); #endif } +bool equivalent(dtype const & a, dtype const & b) { + return a == b; +} + namespace { diff --git a/src/object/class.cpp b/src/object/class.cpp index 9bb9683a31..e03d4e009a 100644 --- a/src/object/class.cpp +++ b/src/object/class.cpp @@ -5,6 +5,7 @@ #include #include // #including this first is an intel6 workaround +#include #include #include @@ -208,7 +209,7 @@ namespace objects { if (static_data_object.tp_dict == 0) { - Py_TYPE(&static_data_object) = &PyType_Type; + Py_SET_TYPE(&static_data_object, &PyType_Type); static_data_object.tp_base = &PyProperty_Type; if (PyType_Ready(&static_data_object)) return 0; @@ -316,7 +317,7 @@ namespace objects { if (class_metatype_object.tp_dict == 0) { - Py_TYPE(&class_metatype_object) = &PyType_Type; + Py_SET_TYPE(&class_metatype_object, &PyType_Type); class_metatype_object.tp_base = &PyType_Type; if (PyType_Ready(&class_metatype_object)) return type_handle(); @@ -332,8 +333,9 @@ namespace objects for (instance_holder* p = kill_me->objects, *next; p != 0; p = next) { next = p->next(); + void* q = dynamic_cast(p); p->~instance_holder(); - instance_holder::deallocate(inst, dynamic_cast(p)); + instance_holder::deallocate(inst, q); } // Python 2.2.1 won't add weak references automatically when @@ -374,12 +376,7 @@ namespace objects // like, so we'll store the total size of the object // there. A negative number indicates that the extra // instance memory is not yet allocated to any holders. -#if PY_VERSION_HEX >= 0x02060000 - Py_SIZE(result) = -#else - result->ob_size = -#endif - -(static_cast(offsetof(instance<>,storage) + instance_size)); + Py_SET_SIZE(result,-static_cast(offsetof(instance<>,storage) + instance_size)); } return (PyObject*)result; } @@ -470,7 +467,7 @@ namespace objects { if (class_type_object.tp_dict == 0) { - Py_TYPE(&class_type_object) = incref(class_metatype().get()); + Py_SET_TYPE(&class_type_object, incref(class_metatype().get())); class_type_object.tp_base = &PyBaseObject_Type; if (PyType_Ready(&class_type_object)) return type_handle(); @@ -506,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 { // Find a registered class object corresponding to id. Return a @@ -568,6 +575,9 @@ namespace objects object m = module_prefix(); if (m) d["__module__"] = m; +#if PY_VERSION_HEX >= 0x03030000 + d["__qualname__"] = qualname(name); +#endif if (doc != 0) d["__doc__"] = doc; @@ -726,28 +736,46 @@ namespace objects } // namespace objects -void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size) +typedef unsigned int alignment_marker_t; + +void* instance_holder::allocate(PyObject* self_, std::size_t holder_offset, std::size_t holder_size, std::size_t alignment) { assert(PyType_IsSubtype(Py_TYPE(Py_TYPE(self_)), &class_metatype_object)); objects::instance<>* self = (objects::instance<>*)self_; - int total_size_needed = holder_offset + holder_size; + int total_size_needed = holder_offset + holder_size + alignment - 1; if (-Py_SIZE(self) >= total_size_needed) { // holder_offset should at least point into the variable-sized part assert(holder_offset >= offsetof(objects::instance<>,storage)); + size_t allocated = holder_size + alignment; + void* storage = (char*)self + holder_offset; + void* aligned_storage = ::boost::alignment::align(alignment, holder_size, storage, allocated); + // Record the fact that the storage is occupied, noting where it starts - Py_SIZE(self) = holder_offset; - return (char*)self + holder_offset; + const size_t offset = reinterpret_cast(aligned_storage) - reinterpret_cast(storage) + holder_offset; + Py_SET_SIZE(self, offset); + return (char*)self + offset; } else { - void* const result = PyMem_Malloc(holder_size); - if (result == 0) + const size_t base_allocation = sizeof(alignment_marker_t) + holder_size + alignment - 1; + void* const base_storage = PyMem_Malloc(base_allocation); + if (base_storage == 0) throw std::bad_alloc(); - return result; + + const uintptr_t x = reinterpret_cast(base_storage) + sizeof(alignment_marker_t); + // 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((char *)aligned_storage - sizeof(alignment_marker_t)); + *marker_storage = static_cast(padding); + return aligned_storage; } } @@ -757,7 +785,9 @@ void instance_holder::deallocate(PyObject* self_, void* storage) throw() objects::instance<>* self = (objects::instance<>*)self_; if (storage != (char*)self + Py_SIZE(self)) { - PyMem_Free(storage); + alignment_marker_t* marker_storage = reinterpret_cast((char *)storage - sizeof(alignment_marker_t)); + void *malloced_storage = (char *) storage - sizeof(alignment_marker_t) - (*marker_storage); + PyMem_Free(malloced_storage); } } diff --git a/src/object/enum.cpp b/src/object/enum.cpp index 10122ad1da..94df8e4aea 100644 --- a/src/object/enum.cpp +++ b/src/object/enum.cpp @@ -49,7 +49,9 @@ extern "C" if (!self->name) { return -#if PY_VERSION_HEX >= 0x03000000 +#if PY_VERSION_HEX >= 0x03030000 + PyUnicode_FromFormat("%S.%S(%ld)", mod, ((PyHeapTypeObject*)(self_->ob_type))->ht_qualname, PyLong_AsLong(self_)); +#elif PY_VERSION_HEX >= 0x03000000 PyUnicode_FromFormat("%S.%s(%ld)", mod, self_->ob_type->tp_name, PyLong_AsLong(self_)); #else PyString_FromFormat("%s.%s(%ld)", PyString_AsString(mod), self_->ob_type->tp_name, PyInt_AS_LONG(self_)); @@ -62,7 +64,9 @@ extern "C" return 0; return -#if PY_VERSION_HEX >= 0x03000000 +#if PY_VERSION_HEX >= 0x03030000 + PyUnicode_FromFormat("%S.%S.%S", mod, ((PyHeapTypeObject*)(self_->ob_type))->ht_qualname, name); +#elif PY_VERSION_HEX >= 0x03000000 PyUnicode_FromFormat("%S.%s.%S", mod, self_->ob_type->tp_name, name); #else PyString_FromFormat("%s.%s.%s", @@ -113,7 +117,6 @@ static PyTypeObject enum_type_object = { #if PY_VERSION_HEX < 0x03000000 | Py_TPFLAGS_CHECKTYPES #endif - | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE, /* tp_flags */ 0, /* tp_doc */ 0, /* tp_traverse */ @@ -146,6 +149,7 @@ static PyTypeObject enum_type_object = { }; object module_prefix(); +object qualname(const char *name); namespace { @@ -153,7 +157,7 @@ namespace { if (enum_type_object.tp_dict == 0) { - Py_TYPE(&enum_type_object) = incref(&PyType_Type); + Py_SET_TYPE(&enum_type_object, incref(&PyType_Type)); #if PY_VERSION_HEX >= 0x03000000 enum_type_object.tp_base = &PyLong_Type; #else @@ -176,6 +180,11 @@ namespace object module_name = module_prefix(); if (module_name) d["__module__"] = module_name; +#if PY_VERSION_HEX >= 0x03030000 + object q = qualname(name); + if (q) + d["__qualname__"] = q; +#endif if (doc) d["__doc__"] = doc; diff --git a/src/object/function.cpp b/src/object/function.cpp index 9d4745d102..fec56768da 100644 --- a/src/object/function.cpp +++ b/src/object/function.cpp @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -107,7 +107,7 @@ function::function( PyObject* p = this; if (Py_TYPE(&function_type) == 0) { - Py_TYPE(&function_type) = &PyType_Type; + Py_SET_TYPE(&function_type, &PyType_Type); ::PyType_Ready(&function_type); } @@ -161,7 +161,6 @@ PyObject* function::call(PyObject* args, PyObject* keywords) const else { // build a new arg tuple, will adjust its size later - assert(max_arity <= static_cast(ssize_t_max)); inner_args = handle<>( PyTuple_New(static_cast(max_arity))); @@ -419,6 +418,30 @@ namespace detail extern char cpp_signature_tag[]; } +object const& function::add_doc(object const& attribute, char const* doc) +{ + str _doc; + + if (docstring_options::show_py_signatures_) + { + _doc += str(const_cast(detail::py_signature_tag)); + } + if (doc != 0 && docstring_options::show_user_defined_) + _doc += doc; + + if (docstring_options::show_cpp_signatures_) + { + _doc += str(const_cast(detail::cpp_signature_tag)); + } + if(_doc) + { + object mutable_attribute(attribute); + mutable_attribute.attr("__doc__")= _doc; + } + + return attribute; +} + void function::add_to_namespace( object const& name_space, char const* name_, object const& attribute, char const* doc) { @@ -489,11 +512,24 @@ void function::add_to_namespace( assert(!PyErr_Occurred()); handle<> name_space_name( - allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast("__name__")))); + allow_null(::PyObject_GetAttrString(name_space.ptr(), const_cast( +#if PY_VERSION_HEX < 0x03030000 + "__name__" +#else + "__qualname__" +#endif + )))); PyErr_Clear(); if (name_space_name) new_func->m_namespace = object(name_space_name); + + object module_name( + PyObject_IsInstance(name_space.ptr(), upcast(&PyModule_Type)) + ? object(name_space.attr("__name__")) + : api::getattr(name_space, "__module__", str()) + ); + new_func->m_module = module_name; } if (PyObject_SetAttr(ns, name.ptr(), attribute.ptr()) < 0) @@ -532,24 +568,7 @@ void function::add_to_namespace( "C++ signature:", f->signature(true))); } */ - str _doc; - - if (docstring_options::show_py_signatures_) - { - _doc += str(const_cast(detail::py_signature_tag)); - } - if (doc != 0 && docstring_options::show_user_defined_) - _doc += doc; - - if (docstring_options::show_cpp_signatures_) - { - _doc += str(const_cast(detail::cpp_signature_tag)); - } - if(_doc) - { - object mutable_attribute(attribute); - mutable_attribute.attr("__doc__")= _doc; - } + add_doc(attribute, doc); } BOOST_PYTHON_DECL void add_to_namespace( @@ -564,6 +583,18 @@ BOOST_PYTHON_DECL void add_to_namespace( function::add_to_namespace(name_space, name, attribute, doc); } +BOOST_PYTHON_DECL object const& add_doc(object const& attribute, char const* doc) +{ +#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 { @@ -670,7 +701,7 @@ extern "C" static PyObject* function_get_module(PyObject* op, void*) { function* f = downcast(op); - object const& ns = f->get_namespace(); + object const& ns = f->get_module(); if (!ns.is_none()) { return python::incref(ns.ptr()); } diff --git a/src/object/function_doc_signature.cpp b/src/object/function_doc_signature.cpp index 41695285ac..18d458698d 100644 --- a/src/object/function_doc_signature.cpp +++ b/src/object/function_doc_signature.cpp @@ -114,23 +114,47 @@ namespace boost { namespace python { namespace objects { 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 ¤t_module_name) { if (s.basename==std::string("void")){ static const char * none = "None"; - return none; + return str(none); } PyTypeObject const * py_type = s.pytype_f?s.pytype_f():0; - if ( py_type ) - return py_type->tp_name; - else{ + if ( py_type ) { + str name(get_qualname(py_type)); + if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) { + // Qualify the type name if it is defined in a different module. + PyObject *type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__"); + if ( + type_module_name + && PyObject_RichCompareBool( + type_module_name, + current_module_name.ptr(), + Py_NE + ) != 0 + ) { + return str("%s.%s" % make_tuple(handle<>(borrowed(type_module_name)), name)); + } + } + return name; + } else { static const char * object = "object"; - return 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; @@ -156,12 +180,12 @@ namespace boost { namespace python { namespace objects { { object kv; if ( arg_names && (kv = arg_names[n-1]) ) - param = str( " (%s)%s" % make_tuple(py_type_str(s[n]),kv[0]) ); + param = str( " (%s)%s" % make_tuple(py_type_str(s[n], current_module_name),kv[0]) ); else - param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n]),"arg", n) ); + param = str(" (%s)%s%d" % make_tuple(py_type_str(s[n], current_module_name),"arg", n) ); } else //we are processing the return type - param = py_type_str(f.get_return_type()); + param = py_type_str(f.get_return_type(), current_module_name); } //an argument - check for default value and append it @@ -199,7 +223,7 @@ namespace boost { namespace python { namespace objects { str param; formal_params.append( - parameter_string(impl, n, f->m_arg_names, cpp_types) + parameter_string(impl, n, f->m_arg_names, f->get_module(), cpp_types) ); // find all the arguments with default values preceeding the arity-n_overloads diff --git a/src/object/inheritance.cpp b/src/object/inheritance.cpp index 7dc9db1cd7..a7b3156e41 100644 --- a/src/object/inheritance.cpp +++ b/src/object/inheritance.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -184,6 +184,7 @@ namespace // map a type to a position in the index inline type_index_t::iterator type_position(class_id type) { + using namespace boost::placeholders; typedef index_entry entry; return std::lower_bound( diff --git a/src/object/iterator.cpp b/src/object/iterator.cpp index 3f6c4adacd..6b885a982c 100644 --- a/src/object/iterator.cpp +++ b/src/object/iterator.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include namespace boost { namespace python { namespace objects { diff --git a/src/object/life_support.cpp b/src/object/life_support.cpp index b7e9aa861e..281c3bffc5 100644 --- a/src/object/life_support.cpp +++ b/src/object/life_support.cpp @@ -93,7 +93,7 @@ PyObject* make_nurse_and_patient(PyObject* nurse, PyObject* patient) if (Py_TYPE(&life_support_type) == 0) { - Py_TYPE(&life_support_type) = &PyType_Type; + Py_SET_TYPE(&life_support_type, &PyType_Type); PyType_Ready(&life_support_type); } diff --git a/src/slice.cpp b/src/slice.cpp index ee55f94846..5ff56185de 100644 --- a/src/slice.cpp +++ b/src/slice.cpp @@ -34,4 +34,14 @@ slice_base::step() const ((PySliceObject*)this->ptr())->step)); } +static struct register_slice_pytype_ptr +{ + register_slice_pytype_ptr() + { + const_cast( + converter::registry::lookup(boost::python::type_id()) + ).m_class_object = &PySlice_Type; + } +}register_slice_pytype_ptr_; + } } } // !namespace boost::python::detail diff --git a/test/Jamfile b/test/Jamfile index 9a5c756956..40115d86cb 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -2,14 +2,16 @@ # Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +require-b2 5.0.1 ; +import-search /boost/config/checks ; + import python ; import os ; -import ../../config/checks/config : requires ; +import config : requires ; lib socket ; -use-project /boost/python : ../build ; -project /boost/python/test +project : requirements gcc:-Wextra qnxnto:socket @@ -28,7 +30,7 @@ rule py-run ( sources * : input-file ? ) : $(input-file) : #requirements BOOST_PYTHON_SUPPRESS_REGISTRY_INITIALIZATION - + ] ; } @@ -52,6 +54,18 @@ rule require-windows ( properties * ) if [ python.configured ] { +alias base_deps : usage-requirements + /boost/align//boost_align + /boost/assert//boost_assert + /boost/config//boost_config + /boost/core//boost_core + /boost/detail//boost_detail + /boost/function//boost_function + /boost/mpl//boost_mpl + /boost/preprocessor//boost_preprocessor + /boost/static_assert//boost_static_assert + /boost/type_traits//boost_type_traits + ; test-suite python : @@ -97,8 +111,8 @@ bpl-test crossmod_exception [ bpl-test andreas_beyer ] [ bpl-test wrapper_held_type ] -[ bpl-test polymorphism2_auto_ptr - : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp +[ bpl-test polymorphism2_auto_ptr + : polymorphism2_auto_ptr.py polymorphism2.py polymorphism2_auto_ptr.cpp : [ requires auto_ptr ] ] @@ -119,7 +133,7 @@ bpl-test crossmod_exception [ bpl-test try : newtest.py m1.cpp m2.cpp ] [ bpl-test const_argument ] [ bpl-test keywords : keywords.cpp keywords_test.py ] - + [ python-extension builtin_converters_ext : builtin_converters.cpp /boost/python//boost_python ] [ bpl-test builtin_converters : test_builtin_converters.py builtin_converters_ext ] @@ -132,6 +146,7 @@ bpl-test crossmod_exception [ bpl-test object ] [ bpl-test class ] +[ bpl-test aligned_class ] [ bpl-test list ] [ bpl-test long ] [ bpl-test dict ] @@ -191,13 +206,13 @@ bpl-test crossmod_opaque # Whenever the cause for the failure of the polymorphism test is found # and fixed, this should be retested. hp_cxx:no ] - + [ python-extension map_indexing_suite_ext : map_indexing_suite.cpp int_map_indexing_suite.cpp a_map_indexing_suite.cpp /boost/python//boost_python ] -[ bpl-test +[ bpl-test map_indexing_suite : map_indexing_suite.py map_indexing_suite_ext ] - + [ run import_.cpp /boost/python//boost_python $(PY) : : import_.py ] # if $(TEST_BIENSTMAN_NON_BUGS) @@ -211,28 +226,29 @@ bpl-test crossmod_opaque # --- unit tests of library components --- -[ compile indirect_traits_test.cpp ] -[ run destroy_test.cpp ] +[ compile indirect_traits_test.cpp : base_deps ] +[ run destroy_test.cpp : : : base_deps ] [ py-run pointer_type_id_test.cpp ] [ py-run bases.cpp ] -[ run if_else.cpp ] +[ run if_else.cpp : : : base_deps ] [ py-run pointee.cpp ] -[ run result.cpp ] +[ run result.cpp : : : base_deps ] -[ compile string_literal.cpp ] +[ compile string_literal.cpp : base_deps ] [ py-compile borrowed.cpp ] [ py-compile object_manager.cpp ] [ py-compile copy_ctor_mutates_rhs.cpp ] [ py-run upcast.cpp ] - + [ py-compile select_holder.cpp ] - -[ run select_from_python_test.cpp ../src/converter/type_id.cpp - : + +[ run select_from_python_test.cpp ../src/converter/type_id.cpp + : : : BOOST_PYTHON_STATIC_LIB $(PY) + base_deps ] diff --git a/test/aligned_class.cpp b/test/aligned_class.cpp new file mode 100644 index 0000000000..55f0fa3c70 --- /dev/null +++ b/test/aligned_class.cpp @@ -0,0 +1,33 @@ +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#include +#include +#include +#include +#include +#include + +using namespace boost::python; + +struct BOOST_ALIGNMENT(32) X +{ + int x; + BOOST_ALIGNMENT(32) float f; + X(int n, float _f) : x(n), f(_f) + { + BOOST_ASSERT((reinterpret_cast(&f) % 32) == 0); + } +}; + +int x_function(X& x) { return x.x;} +float f_function(X& x) { return x.f;} + +BOOST_PYTHON_MODULE(aligned_class_ext) +{ + class_("X", init()); + def("x_function", x_function); + def("f_function", f_function); +} + +#include "module_tail.cpp" diff --git a/test/aligned_class.py b/test/aligned_class.py new file mode 100755 index 0000000000..eb27ac1e96 --- /dev/null +++ b/test/aligned_class.py @@ -0,0 +1,44 @@ +# Distributed under the Boost +# Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +''' +>>> from aligned_class_ext import * + +Ensure sanity: + + >>> x = X(42, 16) + >>> x_function(x) + 42 + >>> f_function(x) + 16.0 + +Demonstrate extraction in the presence of metaclass changes: + + >>> class MetaX(X.__class__): + ... def __new__(cls, *args): + ... return super(MetaX, cls).__new__(cls, *args) + >>> class XPlusMetatype(X): + ... __metaclass__ = MetaX + >>> x = XPlusMetatype(42, 16) + >>> x_function(x) + 42 + >>> f_function(x) + 16.0 + + +''' + +def run(args = None): + import sys + import doctest + + if args is not None: + sys.argv = args + return doctest.testmod(sys.modules.get(__name__)) + +if __name__ == '__main__': + print("running...") + import sys + status = run()[0] + if (status == 0): print("Done.") + sys.exit(status) diff --git a/test/back_reference.cpp b/test/back_reference.cpp index 266ed29125..11e47b3321 100644 --- a/test/back_reference.cpp +++ b/test/back_reference.cpp @@ -99,7 +99,7 @@ BOOST_PYTHON_MODULE(back_reference_ext) .def("set", &Y::set) ; - class_ >("Z", init()) + class_ >("Z", init()) .def("value", &Z::value) .def("set", &Z::set) ; diff --git a/test/copy_ctor_mutates_rhs.cpp b/test/copy_ctor_mutates_rhs.cpp index 41eac495e4..be52c4f327 100644 --- a/test/copy_ctor_mutates_rhs.cpp +++ b/test/copy_ctor_mutates_rhs.cpp @@ -9,14 +9,13 @@ struct foo { - operator std::auto_ptr&() const; + operator std::shared_ptr&() const; }; int main() { using namespace boost::python::detail; BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); - BOOST_STATIC_ASSERT(copy_ctor_mutates_rhs >::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); BOOST_STATIC_ASSERT(!copy_ctor_mutates_rhs::value); return 0; diff --git a/test/fabscript b/test/fabscript index 03e4c6f919..a002fb2bf0 100644 --- a/test/fabscript +++ b/test/fabscript @@ -67,6 +67,7 @@ for t in [('injected',), ('args',), ('raw_ctor',), ('exception_translator',), + ('module_init_exception',), ('test_enum', ['enum_ext']), ('test_cltree', ['cltree']), ('newtest', ['m1', 'm2']), @@ -78,6 +79,8 @@ for t in [('injected',), ('callbacks',), ('defaults',), ('object',), + ('class',), + ('aligned_class',), ('list',), ('long',), ('dict',), @@ -115,10 +118,10 @@ for t in [('injected',), tests.append(extension_test('shared_ptr', condition=set.define.contains('HAS_CXX11'))) -tests.append(extension_test('polymorphism2_auto_ptr', - condition=set.define.contains('HAS_CXX11').not_())) -tests.append(extension_test('auto_ptr', - condition=set.define.contains('HAS_CXX11'))) +#tests.append(extension_test('polymorphism2_auto_ptr', +# condition=set.define.contains('HAS_CXX11').not_())) +#tests.append(extension_test('auto_ptr', +# condition=set.define.contains('HAS_CXX11'))) import_ = binary('import_', ['import_.cpp', src.bpl], features=features|python_libs) if platform.os == 'Windows': diff --git a/test/import_.cpp b/test/import_.cpp index 3e21de0bad..8e03d9b448 100644 --- a/test/import_.cpp +++ b/test/import_.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/test/injected.cpp b/test/injected.cpp index 73e1e14baa..82db3e82e6 100644 --- a/test/injected.cpp +++ b/test/injected.cpp @@ -17,7 +17,7 @@ typedef test_class<> X; X* empty() { return new X(1000); } -std::auto_ptr sum(int a, int b) { return std::auto_ptr(new X(a+b)); } +std::shared_ptr sum(int a, int b) { return std::shared_ptr(new X(a+b)); } boost::shared_ptr product(int a, int b, int c) { diff --git a/test/map_indexing_suite.py b/test/map_indexing_suite.py index e772bb53f9..6d3e57a102 100644 --- a/test/map_indexing_suite.py +++ b/test/map_indexing_suite.py @@ -214,6 +214,13 @@ ... i.data() 4 +##################################################################### +# Test signature... +##################################################################### + +>>> AMap.__iter__.__doc__.strip().split("\\n")[0] +'__iter__( (AMap)arg1) -> __main__.iterator :' + ##################################################################### # END.... ##################################################################### diff --git a/test/module_init_exception.cpp b/test/module_init_exception.cpp new file mode 100644 index 0000000000..d8cec57d3a --- /dev/null +++ b/test/module_init_exception.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2003 Rational Discovery LLC +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#include +#include + +using namespace boost::python; + +BOOST_PYTHON_MODULE(module_init_exception_ext) +{ + throw std::runtime_error("Module init failed"); +} diff --git a/test/module_init_exception.py b/test/module_init_exception.py new file mode 100644 index 0000000000..3da53e1956 --- /dev/null +++ b/test/module_init_exception.py @@ -0,0 +1,12 @@ +# Copyright (C) 2003 Rational Discovery LLC. Distributed under the Boost +# Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +# at http://www.boost.org/LICENSE_1_0.txt) + +print("running...") + +try: + import module_init_exception_ext +except RuntimeError as e: + print(e) + +print("Done.") diff --git a/test/nested.cpp b/test/nested.cpp index de656d2b8b..3a0d05e5ea 100644 --- a/test/nested.cpp +++ b/test/nested.cpp @@ -4,6 +4,8 @@ // http://www.boost.org/LICENSE_1_0.txt) #include #include +#include +#include #include #include #include "test_class.hpp" @@ -16,6 +18,8 @@ typedef test_class<> X; typedef test_class<1> Y; +enum color { red = 0, blue = 1, green = 2 }; + std::ostream& operator<<(std::ostream& s, X const& x) { return s << x.value(); @@ -26,11 +30,13 @@ std::ostream& operator<<(std::ostream& s, Y const& x) return s << x.value(); } +void test_function(const X& x, const Y& y) {} BOOST_PYTHON_MODULE(nested_ext) { using namespace boost::python; + { // Establish X as the current scope. scope x_class = class_("X", init()) @@ -42,6 +48,17 @@ BOOST_PYTHON_MODULE(nested_ext) class_("Y", init()) .def(str(self)) ; + + // so will the enum `color` + enum_("color") + .value("red", red) + .value("green", green) + .value("blue", blue) + ; + } + + // The generated docstring will use the fully-qualified name of Y + def("test_function", &test_function); } diff --git a/test/nested.py b/test/nested.py index 720790173c..657d100a71 100644 --- a/test/nested.py +++ b/test/nested.py @@ -13,14 +13,35 @@ >>> X.__name__ 'X' - >>> X.Y + >>> X.Y # doctest: +py2 + + >>> X.Y # doctest: +py3 + >>> X.Y.__module__ 'nested_ext' >>> X.Y.__name__ '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: sys.argv = args - return doctest.testmod(sys.modules.get(__name__)) + + py2 = doctest.register_optionflag("py2") + py3 = doctest.register_optionflag("py3") + + class ConditionalChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if (optionflags & py3) and (sys.version_info[0] < 3): + return True + if (optionflags & py2) and (sys.version_info[0] >= 3): + return True + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + runner = doctest.DocTestRunner(ConditionalChecker()) + for test in doctest.DocTestFinder().find(sys.modules.get(__name__)): + runner.run(test) + + return doctest.TestResults(runner.failures, runner.tries) if __name__ == '__main__': print("running...") diff --git a/test/numpy/dtype.py b/test/numpy/dtype.py index a27ee0f55d..a2eabb58e2 100644 --- a/test/numpy/dtype.py +++ b/test/numpy/dtype.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -15,7 +15,7 @@ class DtypeTestCase(unittest.TestCase): def assertEquivalent(self, a, b): - return self.assert_(dtype_ext.equivalent(a, b), "%r is not equivalent to %r") + return self.assertTrue(dtype_ext.equivalent(a, b), "%r is not equivalent to %r") def testIntegers(self): for bits in (8, 16, 32, 64): diff --git a/test/numpy/indexing.py b/test/numpy/indexing.py index ebd9dcbabb..3fb9adb4c0 100644 --- a/test/numpy/indexing.py +++ b/test/numpy/indexing.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. diff --git a/test/numpy/ndarray.py b/test/numpy/ndarray.py index 2acc384a52..13f3c73e42 100644 --- a/test/numpy/ndarray.py +++ b/test/numpy/ndarray.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -19,7 +19,7 @@ def testNdzeros(self): a1 = ndarray_ext.zeros(shape,dt) a2 = v.reshape(a1.shape) self.assertEqual(shape,a1.shape) - self.assert_((a1 == a2).all()) + self.assertTrue((a1 == a2).all()) def testNdzeros_matrix(self): for dtp in (numpy.int16, numpy.int32, numpy.float32, numpy.complex128): @@ -28,7 +28,7 @@ def testNdzeros_matrix(self): a1 = ndarray_ext.zeros_matrix(shape, dt) a2 = numpy.matrix(numpy.zeros(shape, dtype=dtp)) self.assertEqual(shape,a1.shape) - self.assert_((a1 == a2).all()) + self.assertTrue((a1 == a2).all()) self.assertEqual(type(a1), type(a2)) def testNdarray(self): @@ -38,8 +38,8 @@ def testNdarray(self): dt = numpy.dtype(dtp) a1 = ndarray_ext.array(a) a2 = ndarray_ext.array(a,dt) - self.assert_((a1 == v).all()) - self.assert_((a2 == v).all()) + self.assertTrue((a1 == v).all()) + self.assertTrue((a2 == v).all()) for shape in ((60,),(6,10),(4,3,5),(2,2,3,5)): a1 = a1.reshape(shape) self.assertEqual(shape,a1.shape) diff --git a/test/numpy/shapes.py b/test/numpy/shapes.py index d0a0099ca6..28c74b7b18 100644 --- a/test/numpy/shapes.py +++ b/test/numpy/shapes.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. diff --git a/test/numpy/templates.py b/test/numpy/templates.py index 8290b13a07..9c21622881 100755 --- a/test/numpy/templates.py +++ b/test/numpy/templates.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -18,7 +18,7 @@ def testTemplates(self): a1 = numpy.zeros(shape, dtype=dtype) a2 = v.reshape(a1.shape) templates_ext.fill(a1) - self.assert_((a1 == a2).all()) + self.assertTrue((a1 == a2).all()) a1 = numpy.zeros((12,), dtype=numpy.float64) self.assertRaises(TypeError, templates_ext.fill, a1) a1 = numpy.zeros((12,2,3), dtype=numpy.float32) diff --git a/test/numpy/ufunc.py b/test/numpy/ufunc.py index e820121ee1..1fa3090b3e 100755 --- a/test/numpy/ufunc.py +++ b/test/numpy/ufunc.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # Copyright Jim Bosch & Ankit Daftery 2010-2012. # Distributed under the Boost Software License, Version 1.0. @@ -8,7 +8,10 @@ import ufunc_ext import unittest import numpy -from numpy.testing.utils import assert_array_almost_equal +try: + from numpy.testing import assert_array_almost_equal +except ImportError: + from numpy.testing.utils import assert_array_almost_equal class TestUnary(unittest.TestCase): @@ -24,7 +27,7 @@ def testArray(self): assert_array_almost_equal(b, a*2.0) c = numpy.zeros(5, dtype=float) d = f(a,output=c) - self.assert_(c is d) + self.assertTrue((c == d).all()) assert_array_almost_equal(d, a*2.0) def testList(self): @@ -47,7 +50,7 @@ def testArray(self): assert_array_almost_equal(f(a,b), (a*2+b*3)) c = numpy.zeros(5, dtype=float) d = f(a,b,output=c) - self.assert_(c is d) + self.assertTrue((c == d).all()) assert_array_almost_equal(d, a*2 + b*3) assert_array_almost_equal(f(a, 2.0), a*2 + 6.0) assert_array_almost_equal(f(1.0, b), 2.0 + b*3) diff --git a/test/operators_wrapper.cpp b/test/operators_wrapper.cpp index 12f30048d0..e62ead16f8 100644 --- a/test/operators_wrapper.cpp +++ b/test/operators_wrapper.cpp @@ -36,7 +36,7 @@ BOOST_PYTHON_MODULE( operators_wrapper_ext ) ; scope().attr("v") = vector(); - std::auto_ptr dp(new dvector); - register_ptr_to_python< std::auto_ptr >(); + std::shared_ptr dp(new dvector); + register_ptr_to_python< std::shared_ptr >(); scope().attr("d") = dp; } diff --git a/test/pickle1.py b/test/pickle1.py index b8f4efd9b0..0df59a4b3a 100644 --- a/test/pickle1.py +++ b/test/pickle1.py @@ -9,8 +9,10 @@ 1 >>> pickle1_ext.world.__name__ 'world' - >>> pickle1_ext.world('Hello').__reduce__() + >>> pickle1_ext.world('Hello').__reduce__() # doctest: +PY310 (, ('Hello',)) + >>> pickle1_ext.world('Hello').__reduce__() # doctest: +PY311 + (, ('Hello',), None) >>> wd = pickle1_ext.world('California') >>> pstr = pickle.dumps(wd) >>> wl = pickle.loads(pstr) @@ -31,7 +33,27 @@ def run(args = None): if args is not None: sys.argv = args - return doctest.testmod(sys.modules.get(__name__)) + + # > https://docs.python.org/3.11/library/pickle.html#object.__reduce__ + # object.__reduce__() returns + # - python 3.10 or prior: a 2-element tuple + # - python 3.11 or later: a 3-element tuple (object's state added) + PY310 = doctest.register_optionflag("PY310") + PY311 = doctest.register_optionflag("PY311") + + class ConditionalChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if (optionflags & PY311) and (sys.version_info[:2] < (3, 11)): + return True + if (optionflags & PY310) and (sys.version_info[:2] >= (3, 11)): + return True + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + runner = doctest.DocTestRunner(ConditionalChecker()) + for test in doctest.DocTestFinder().find(sys.modules.get(__name__)): + runner.run(test) + + return doctest.TestResults(runner.failures, runner.tries) if __name__ == '__main__': print("running...") diff --git a/test/pickle4.py b/test/pickle4.py index be813bbb13..3cf4d7241f 100644 --- a/test/pickle4.py +++ b/test/pickle4.py @@ -12,8 +12,10 @@ 1 >>> pickle4_ext.world.__name__ 'world' - >>> pickle4_ext.world('Hello').__reduce__() + >>> pickle4_ext.world('Hello').__reduce__() # doctest: +PY310 (, ('Hello',)) + >>> pickle4_ext.world('Hello').__reduce__() # doctest: +PY311 + (, ('Hello',), None) >>> wd = pickle4_ext.world('California') >>> pstr = pickle.dumps(wd) >>> wl = pickle.loads(pstr) @@ -29,7 +31,27 @@ def run(args = None): if args is not None: sys.argv = args - return doctest.testmod(sys.modules.get(__name__)) + + # > https://docs.python.org/3.11/library/pickle.html#object.__reduce__ + # object.__reduce__() returns + # - python 3.10 or prior: a 2-element tuple + # - python 3.11 or later: a 3-element tuple (object's state added) + PY310 = doctest.register_optionflag("PY310") + PY311 = doctest.register_optionflag("PY311") + + class ConditionalChecker(doctest.OutputChecker): + def check_output(self, want, got, optionflags): + if (optionflags & PY311) and (sys.version_info[:2] < (3, 11)): + return True + if (optionflags & PY310) and (sys.version_info[:2] >= (3, 11)): + return True + return doctest.OutputChecker.check_output(self, want, got, optionflags) + + runner = doctest.DocTestRunner(ConditionalChecker()) + for test in doctest.DocTestFinder().find(sys.modules.get(__name__)): + runner.run(test) + + return doctest.TestResults(runner.failures, runner.tries) if __name__ == '__main__': print("running...") diff --git a/test/properties.cpp b/test/properties.cpp index d338beb915..aa1b0a05cf 100644 --- a/test/properties.cpp +++ b/test/properties.cpp @@ -64,6 +64,7 @@ BOOST_PYTHON_MODULE(properties_ext) class_("X", init() ) //defining read only property .add_property( "value_r", &X::get_value ) + .add_property( "value_r_f", make_function(&X::get_value) ) .add_property( "value_r_ds", &X::get_value, "value_r_ds is read-only") //defining read \ write property .add_property( "value_rw", &X::get_value, &X::set_value ) diff --git a/test/properties.py b/test/properties.py index 1bc7a624ba..e95d59bef2 100644 --- a/test/properties.py +++ b/test/properties.py @@ -20,6 +20,9 @@ >>> x1.value_r 1 +>>> x1.value_r_f +1 + value read - write >>> x1.value_rw 1 @@ -53,11 +56,10 @@ class instance count from object: 1 as expected you can't assign new value to read only property ->>> x1.value_r = 2 +>>> x1.value_r = 2 # doctest: +ELLIPSIS Traceback (most recent call last): - File "properties.py", line 49, in ? - x1.value_r = 2 -AttributeError: can't set attribute + ... +AttributeError: ... setting value_rw to 2. value_direct: >>> x1.value_rw = 2 @@ -84,8 +86,27 @@ class instance count from object: >>> assert properties.X.value_rw_ds.__doc__ == "value_rw_ds is read-write" +>>> properties.X.value_r_f.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' + +>>> properties.X.value_rw_ds.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' + +>>> properties.X.value_rw_ds.fset.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1, (int)arg2) -> None :' + +>>> properties.X.value_rw_ds.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' + +>>> properties.X.value_direct.fset.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1, (int)arg2) -> None :' + +>>> properties.X.value_direct.fget.__doc__.strip().split("\\n")[0] +'None( (properties_ext.X)arg1) -> int :' """ +# FIXME: cases to cover: pointer-to-member, preconstructed function + #import sys; sys.path.append(r'P:\Actimize4.0\smart_const\py_smart_const___Win32_Debug') import properties_ext as properties diff --git a/test/select_holder.cpp b/test/select_holder.cpp index 8650bd06a0..77aac67868 100644 --- a/test/select_holder.cpp +++ b/test/select_holder.cpp @@ -62,14 +62,14 @@ int test_main(int, char * []) assert_holder >(); - assert_holder - ,pointer_holder,Base> >(); + assert_holder + ,pointer_holder,Base> >(); - assert_holder - ,pointer_holder_back_reference,Base> >(); + assert_holder + ,pointer_holder_back_reference,Base> >(); - assert_holder - ,pointer_holder_back_reference,BR> > (); + assert_holder + ,pointer_holder_back_reference,BR> > (); return 0; } diff --git a/test/shared_ptr.py b/test/shared_ptr.py index d250ae7eca..4ef88f78d8 100644 --- a/test/shared_ptr.py +++ b/test/shared_ptr.py @@ -38,7 +38,7 @@ 12 >>> try: modify(p) ... except TypeError: pass -... else: 'print(expected a TypeError)' +... else: print('expected a TypeError') >>> look(None) -1 >>> store(p) @@ -61,7 +61,7 @@ 13 >>> try: modify(z) ... except TypeError: pass -... else: 'print(expected a TypeError)' +... else: print('expected a TypeError') >>> Z.get() # should be None >>> store(z) @@ -84,7 +84,7 @@ 17 >>> try: modify(x) ... except TypeError: pass -... else: 'print(expected a TypeError)' +... else: print('expected a TypeError') >>> look(None) -1 >>> store(x) diff --git a/test/slice.py b/test/slice.py index c58bbc0299..041934cf57 100644 --- a/test/slice.py +++ b/test/slice.py @@ -33,6 +33,8 @@ 0 >>> check_slice_get_indices( slice( -2, -5, -2)) 6 +>>> check_slice_get_indices.__doc__.strip().split('\\n')[0] +'check_slice_get_indices( (slice)arg1) -> int :' """ # Performs an affirmative and negative argument resolution check. diff --git a/test/test_cltree.py b/test/test_cltree.py index 2127b7cdb6..d5df6fc5a0 100644 --- a/test/test_cltree.py +++ b/test/test_cltree.py @@ -1,7 +1,7 @@ # Copyright David Abrahams 2004. Distributed under the Boost # Software License, Version 1.0. (See accompanying # file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#!/usr/bin/env python +#!/usr/bin/env python3 from cltree import basic,symbol,constant,variable diff --git a/test/upcast.cpp b/test/upcast.cpp index 255429f168..e005900410 100644 --- a/test/upcast.cpp +++ b/test/upcast.cpp @@ -13,7 +13,7 @@ int main() { PyTypeObject o; Y y; - BOOST_TEST(&Py_REFCNT(boost::python::upcast(&o)) == &Py_REFCNT(&o)); - BOOST_TEST(&Py_REFCNT(boost::python::upcast(&y)) == &Py_REFCNT(&y)); + BOOST_TEST(boost::python::upcast(&o) == reinterpret_cast(&o)); + BOOST_TEST(boost::python::upcast(&y) == &y); return boost::report_errors(); } diff --git a/test/wrapper_held_type.cpp b/test/wrapper_held_type.cpp index e99422796e..ef494924b9 100644 --- a/test/wrapper_held_type.cpp +++ b/test/wrapper_held_type.cpp @@ -20,12 +20,12 @@ struct data } }; -std::auto_ptr create_data() +std::shared_ptr create_data() { - return std::auto_ptr( new data ); + return std::shared_ptr( new data ); } -void do_nothing( std::auto_ptr& ){} +void do_nothing( std::shared_ptr& ){} namespace bp = boost::python; @@ -59,7 +59,7 @@ struct data_wrapper : data, bp::wrapper< data > BOOST_PYTHON_MODULE(wrapper_held_type_ext) { - bp::class_< data_wrapper, std::auto_ptr< data > >( "data" ) + bp::class_< data_wrapper, std::shared_ptr< data > >( "data" ) .def( "id", &data::id, &::data_wrapper::default_id ); bp::def( "do_nothing", &do_nothing );