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

Compare commits

..

1 Commits

Author SHA1 Message Date
Stefan Seefeld
3c23f859fd Fix id clash in hierarchical tocs. 2016-10-17 08:25:39 -04:00
282 changed files with 4449 additions and 2188 deletions

View File

@@ -1,7 +0,0 @@
# -*- python -*-
from faber.tools.boost import boostbook
from faber.tools.python import python
bb = boostbook(prefix='/usr/share/boostbook')
p = python(command='$PYTHON')

229
.ci/install.ps1 Normal file
View File

@@ -0,0 +1,229 @@
# 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)
(?<major>\d+)
\.
(?<minor>\d+)
\.
(?<micro>\d+)
(?<prerelease>[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

88
.ci/run_with_env.cmd Normal file
View File

@@ -0,0 +1,88 @@
:: 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
)

58
.ci/upload_docs.sh Executable file
View File

@@ -0,0 +1,58 @@
#!/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`
# bin.SCons 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 bin.SCons
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

View File

@@ -1,37 +0,0 @@
name: deploy documentation
on: [push, pull_request]
jobs:
deploy:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: setup
run: |
sudo apt-get update
sudo apt-get install \
libboost1.71-tools-dev \
python3 \
python3-numpy \
python3-sphinx \
xsltproc \
docbook-xsl
sudo python3 -m pip install --upgrade pip
sudo python3 -m pip install faber
- name: build
run: |
sed -e "s/\$PYTHON/python3/g" .ci/faber > ~/.faber
faber --builddir=build doc.html
if [ "${GITHUB_REF##*/}" == master ]; then
echo "destination_dir=doc/html" >> $GITHUB_ENV
else
echo "destination_dir=doc/develop/html" >> $GITHUB_ENV
fi
- name: deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: build/doc/html
destination_dir: ${{ env.destination_dir }}
keep_files: true

View File

@@ -1,45 +0,0 @@
name: Test OSX
on: [push, pull_request]
jobs:
build:
runs-on: macOS-latest
strategy:
fail-fast: false
matrix:
python-version: [3.6]
cxx: [clang++]
std: [c++98, c++11, c++14] # TODO: c++17 is failing !
steps:
- uses: actions/checkout@v2
- name: setup python
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: setup prerequisites
run: |
brew install boost
python -m pip install --upgrade pip
python -m pip install setuptools faber
- name: build
run: |
python --version
${{ matrix.cxx }} --version
faber -v
sed -e "s/\$PYTHON/python/g" .ci/faber > ~/.faber
faber \
--builddir=build \
cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \
-j`sysctl -n hw.ncpu`
- name: test
run: |
faber \
--builddir=build\
cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \
-j`sysctl -n hw.ncpu` \
test.report

View File

@@ -1,51 +0,0 @@
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++98, c++11, c++14, c++17]
include:
# Add the appropriate docker image for each compiler.
# The images from teeks99/boost-python-test already have boost::python
# pre-reqs installed, see:
# https://github.com/teeks99/boost-python-test-docker
- cxx: clang++
docker-img: teeks99/boost-python-test:clang-12_1.76.0
- cxx: g++
docker-img: teeks99/boost-python-test:gcc-10_1.76.0
container:
image: ${{ matrix.docker-img }}
steps:
- uses: actions/checkout@v2
- 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 }} \
-j`nproc`
- name: test
run: |
faber \
--with-boost-include=${BOOST_PY_DEPS} \
--builddir=build \
cxx.name=${{ matrix.cxx }} \
cxxflags=-std=${{ matrix.std }} \
-j`nproc` \
test.report

View File

@@ -1,39 +0,0 @@
name: Test Windows
on: [push, pull_request]
jobs:
build:
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
python-version: [3.7]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: setup boost prerequisites
uses: lukka/run-vcpkg@v6
with:
vcpkgGitCommitId: '8a9a97315aefb3f8bc5d81bf66ca0025938b9c91'
vcpkgDirectory: '${{ runner.workspace }}/vcpkg'
vcpkgTriplet: x64-windows
vcpkgArguments: boost-config boost-core boost-function boost-graph boost-iterator boost-lexical-cast boost-mpl boost-preprocessor boost-smart-ptr boost-static-assert boost-align
- name: setup faber
#shell: 'bash'
run: |
python -m pip install --upgrade pip
python -m pip install setuptools faber numpy
faber --info=tools cxx
- name: build
shell: cmd
run: |
faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}/vcpkg/installed/x64-windows/include -j4
- name: test
shell: cmd
run: |
faber --builddir=build cxx.name=msvc --with-boost-include=${{ runner.workspace }}/vcpkg/installed/x64-windows/include -j4 test.report

105
.travis.yml Normal file
View File

@@ -0,0 +1,105 @@
#
# 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)
sudo: required
dist: trusty
language: cpp
env:
global:
- secure: BRNUkxN3p8f+uYKWC3Hr0VPqZA0PxbWr1DJlcI4hbiZtzKhMCWjDmd9UW9CzzexqeOxpd+9s0G87qvOur+wMSVxugDxtTesZrh1czXHeSVxgQrYD783XJtQJ9aYypbChkiboRD6Xpmbq7itwMuHBJMFtCuDxMynpU1jWwkyTf2Y=
matrix:
include:
#- compiler: gcc
# env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++98
#- compiler: gcc
# env: CXX=g++ PYTHON=python CXXFLAGS=-std=c++11
#- compiler: gcc
# env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++98
#- compiler: gcc
# env: CXX=g++ PYTHON=python3 CXXFLAGS=-std=c++11
#- compiler: clang
# # clang generates an 'illegal instruction' error in the NumPy check.
# # Perhaps we need to upgrade clang to a newer version ?
# env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++98 OPTIONS=--no-numpy
#- compiler: clang
# env: CXX=clang++ PYTHON=python3 CXXFLAGS=-std=c++11 OPTIONS=--no-numpy
- env: PYTHON=python DOC=1
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- scons
- gcc-4.8
- g++-4.8
- clang
- python-numpy
- python-sphinx
- python3-dev
- python3-numpy
- libboost-all-dev
- xsltproc
- docbook-xsl
- python-docutils
- python-pip
cache:
directories:
- $HOME/Boost
before_install:
# The Trusty image has several Python versions pre-installed compiled with
# conflicting UCS2 and UCS4 unicode. Modify the PATH to skip the TravisCI python.
# See https://github.com/travis-ci/travis-ci/issues/4948 for details.
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
install:
# Install our own version of Boost (the subset we need) as the system version is
# too old (for C++11 support).
- rm -rf $HOME/Boost
- |
set -e
if [ ! -d $HOME/Boost ]; then
echo "rebuilding Boost prerequisites"
wget https://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.gz/download
tar xf download
pushd boost_1_61_0
./bootstrap.sh
./b2 tools/bcp
mkdir -p $HOME/Boost
dist/bin/bcp python tools/boostbook tools/quickbook $HOME/Boost &> /dev/null
popd
fi
before_script:
- scons --version
script:
- scons config --python=$PYTHON --boost-include=$HOME/Boost $OPTIONS
- |
if [ "$DOC" ]; then
scons doc
else
scons && scons test
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

View File

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

View File

@@ -2,8 +2,6 @@
# Synopsis
[![Join the chat at https://gitter.im/boostorg/python](https://badges.gitter.im/boostorg/python.svg)](https://gitter.im/boostorg/python?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
Welcome to Boost.Python, a C++ library which enables seamless interoperability between C++ and the Python programming language. The library includes support for:
* References and Pointers
@@ -21,7 +19,7 @@ See the [Boost.Python](http://boostorg.github.io/python) documentation for detai
**Hint :** Check out the [development version](http://boostorg.github.io/python/develop) of the documentation to see work in progress.
# Building ![Test Ubuntu](https://github.com/boostorg/python/workflows/Test%20Ubuntu/badge.svg) ![Test OSX](https://github.com/boostorg/python/workflows/Test%20OSX/badge.svg) ![Test Windows](https://github.com/boostorg/python/workflows/Test%20Windows/badge.svg)
# Building ![Build Status](https://travis-ci.org/boostorg/python.svg?branch=develop)
While Boost.Python is part of the Boost C++ Libraries super-project, and thus can be compiled as part of Boost, it can also be compiled and installed stand-alone, i.e. against a pre-installed Boost package.
@@ -29,14 +27,27 @@ While Boost.Python is part of the Boost C++ Libraries super-project, and thus ca
* [Python](http://www.python.org)
* [Boost](http://www.boost.org)
* [Faber](https://stefanseefeld.github.io/faber)
* [SCons](http://www.scons.org)
## Configure
Simply run
```
scons config [options]
```
to prepare a build. See `scons -h` for a description of the available options. For example
```
scons config --boost=/path/to/boost --python=/path/to/python
```
will configure Boost.Python to be built against the two specific versions of Boost and Python.
## Build
Run
```
faber
scons
```
to build the library.
@@ -45,7 +56,7 @@ to build the library.
Run
```
faber test.report
scons test
```
to run the tests.
@@ -54,6 +65,6 @@ to run the tests.
Run
```
faber doc.html
scons doc
```
to build the documentation.

100
SConstruct Normal file
View File

@@ -0,0 +1,100 @@
# -*- python -*-
#
# 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)
import SCons.Script.Main
import config
import config.ui
import platform
import os
import subprocess
import re
#
# We try to mimic the typical autotools-workflow.
#
# * In a 'configure' step all the essential build parameters are established
# (either by explicit command-line arguments or from configure checks)
# * A subsequent build step can then simply read the cached variables, so
# users don't have to memorize and re-issue the arguments on each subsequent
# invocation, and neither do the config checks need to be re-run.
#
# The essential part here is to define a 'config' target, which removes any
# caches that may still be lingering around, then runs the checks.
if 'config' in COMMAND_LINE_TARGETS:
# Clear the cache
try: os.remove('bin.SCons/config.py')
except: pass
if not os.path.exists('bin.SCons/'):
os.mkdir('bin.SCons/')
vars = Variables('bin.SCons/config.py', ARGUMENTS)
config.add_options(vars)
arch = ARGUMENTS.get('arch', platform.machine())
env_vars = {}
if 'CXX' in os.environ: env_vars['CXX'] = os.environ['CXX']
if 'CXXFLAGS' in os.environ: env_vars['CXXFLAGS'] = os.environ['CXXFLAGS'].split()
env = Environment(toolpath=['config/tools'],
tools=['default', 'libs', 'tests', 'doc', 'sphinx4scons'],
variables=vars,
TARGET_ARCH=arch,
**env_vars)
if 'gcc' in env['TOOLS']:
# Earlier SCons versions (~ 2.3.0) can't handle CXX=clang++.
version = subprocess.check_output([env['CXX'], '--version'])
match = re.search(r'[0-9]+(\.[0-9]+)+', version)
if match:
version = match.group(0)
else:
version = 'unknown'
env['CXXVERSION'] = version
Help(config.ui.help(vars, env) + """
Variables are saved in bin.SCons/config.py and persist between scons invocations.
""")
if GetOption('help'):
Return()
build_dir = config.prepare_build_dir(env)
config_log = '{}/config.log'.format(build_dir)
# configure
SConsignFile('{}/.sconsign'.format(build_dir))
#env.Decider('MD5-timestamp')
env.Decider('timestamp-newer')
checks = config.get_checks(env)
if 'config' in COMMAND_LINE_TARGETS:
conf=env.Configure(custom_tests=checks, log_file=config_log, conf_dir=build_dir)
if False in (getattr(conf, c)() for c in checks):
Exit(1)
env = conf.Finish()
vars.Save('bin.SCons/config.py', env)
if not os.path.exists(config_log):
print('Please run `scons config` first. (See `scons -h` for available options.)')
Exit(1)
if not GetOption('verbose'):
config.ui.pretty_output(env)
# build
env['BPL_VERSION'] = '1.62'
for e in config.variants(env):
variant_dir=e.subst("$BOOST_CURRENT_VARIANT_DIR")
e.SConscript('src/SConscript', variant_dir=variant_dir + '/src',
exports = { 'env' : e.Clone(BOOST_LIB = 'python') })
if 'test' in COMMAND_LINE_TARGETS:
test_env = e.Clone(BOOST_LIB = 'python', BOOST_TEST = True)
test_env.BoostUseLib('python')
e.SConscript('test/SConscript', variant_dir=variant_dir + '/test',
exports = { 'env' : test_env })
if 'doc' in COMMAND_LINE_TARGETS:
env.SConscript('doc/SConscript', variant_dir='bin.SCons/doc',
exports = { 'env' : e.Clone(BOOST_LIB = 'python') })

98
appveyor.yml Normal file
View File

@@ -0,0 +1,98 @@
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"
BOOST_PREFIX: C:\Libraries\boost_1_60_0
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:\\Python27"
PYTHON_VERSION: "2.7.x" # currently 2.7.9
PYTHON_ARCH: "32"
ARCH: "x86"
#- PYTHON: "C:\\Python27-x64"
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
# PYTHON_ARCH: "64"
# ARCH: "x86_64"
#- PYTHON: "C:\\Python35"
# PYTHON_VERSION: "3.5.x" # currently 3.4.3
# PYTHON_ARCH: "32"
#- PYTHON: "C:\\Python35-x64"
# PYTHON_VERSION: "3.5.x" # currently 3.4.3
# PYTHON_ARCH: "64"
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/\""
- 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.
- "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
- easy_install scons
#- "%CMD_IN_ENV% pip install -r dev-requirements.txt"
build_script:
# Build the compiled extension
#- "%CMD_IN_ENV% python setup.py build"
- scons config arch=%ARCH% --boost-include=%BOOST_PREFIX%
- scons arch=%ARCH%
test_script:
# Run the project tests
#- "%CMD_IN_ENV% python setup.py nosetests"
- scons test arch=%ARCH% --verbose
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
#

View File

@@ -6,7 +6,7 @@ import os ;
import indirect ;
import modules ;
import feature ;
import property ;
import python ;
if ! [ python.configured ] && ! ( --without-python in [ modules.peek : ARGV ] )
@@ -30,138 +30,122 @@ else
;
}
rule find-py3-version
{
local versions = [ feature.values python ] ;
local py3ver ;
for local v in $(versions)
{
if $(v) >= 3.0
{
py3ver = $(v) ;
}
}
return $(py3ver) ;
}
py3-version = [ find-py3-version ] ;
project boost/python
: source-location ../src
: requirements
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@$(__name__).tag
;
rule tag ( name : type ? : property-set )
{
local result = $(name) ;
if $(type) in STATIC_LIB SHARED_LIB IMPORT_LIB
{
if $(name) = boost_python && $(PYTHON_ID)
{
result = $(result)-$(PYTHON_ID) ;
}
}
# forward to the boost tagging rule
return [ indirect.call $(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
$(result) : $(type) : $(property-set) ] ;
}
rule cond ( test ? : yes * : no * ) { if $(test) { return $(yes) ; } else { return $(no) ; } }
rule unless ( test ? : yes * : no * ) { if ! $(test) { return $(yes) ; } else { return $(no) ; } }
local rule eq ( a : b ) { if $(a) = $(b) { return 1 ; } }
lib boost_python
: # sources
list.cpp
long.cpp
dict.cpp
tuple.cpp
str.cpp
slice.cpp
converter/from_python.cpp
converter/registry.cpp
converter/type_id.cpp
object/enum.cpp
object/class.cpp
object/function.cpp
object/inheritance.cpp
object/life_support.cpp
object/pickle_support.cpp
errors.cpp
module.cpp
converter/builtin_converters.cpp
converter/arg_to_python_base.cpp
object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp
object_operators.cpp
wrapper.cpp
import.cpp
exec.cpp
object/function_doc_signature.cpp
: # requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE
# On Windows, all code using Python has to link to the Python
# import library.
#
# On *nix we never link libboost_python to libpython. When
# extending Python, all Python symbols are provided by the
# Python interpreter executable. When embedding Python, the
# client executable is expected to explicitly link to
# /python//python (the target representing libpython) itself.
#
# python_for_extensions is a target defined by Boost.Build to
# provide the Python include paths, and on Windows, the Python
# import library, as usage requirements.
[ cond [ python.configured ] : <library>/python//python_for_extensions ]
# we prevent building when there is no python available
# as it's not possible anyway, and to cause dependents to
# fail to build
[ unless [ python.configured ] : <build>no ]
<dependency>config-warning
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@python-tag
<conditional>@python.require-py
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
numpy-include = [ python.numpy-include ] ;
lib boost_numpy
: # sources
numpy/dtype.cpp
numpy/matrix.cpp
numpy/ndarray.cpp
numpy/numpy.cpp
numpy/scalars.cpp
numpy/ufunc.cpp
: # requirements
<link>static:<define>BOOST_NUMPY_STATIC_LIB
<define>BOOST_NUMPY_SOURCE
[ cond [ python.numpy ] : <library>/python//python_for_extensions ]
[ unless [ python.numpy ] : <build>no ]
<library>/python//numpy
<library>boost_python
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
-<tag>@$(BOOST_JAMROOT_MODULE)%$(BOOST_JAMROOT_MODULE).tag
<tag>@python-tag
<conditional>@python.require-py
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_NUMPY_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
# boost-install creates `stage` and `install` targets
#
# `stage` stages (builds and copies into `stage/lib`) the given libraries
# `boost_python` and `boost_numpy` and their dependencies and is similar
# to issuing `b2 --with-python stage` from top level
#
# `install` installs the two libraries and their dependencies and is similar
# to issuing `b2 --with-python install` from top level
if [ python.configured ]
{
if [ python.numpy ]
{
boost-install boost_python boost_numpy ;
}
else
{
boost-install boost_python ;
}
}
else
rule lib_boost_python ( is-py3 ? )
{
# 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
lib [ cond $(is-py3) : boost_python3 : boost_python ]
: # sources
numeric.cpp
list.cpp
long.cpp
dict.cpp
tuple.cpp
str.cpp
slice.cpp
alias stage : config-warning ;
explicit stage ;
converter/from_python.cpp
converter/registry.cpp
converter/type_id.cpp
object/enum.cpp
object/class.cpp
object/function.cpp
object/inheritance.cpp
object/life_support.cpp
object/pickle_support.cpp
errors.cpp
module.cpp
converter/builtin_converters.cpp
converter/arg_to_python_base.cpp
object/iterator.cpp
object/stl_iterator.cpp
object_protocol.cpp
object_operators.cpp
wrapper.cpp
import.cpp
exec.cpp
object/function_doc_signature.cpp
: # requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<define>BOOST_PYTHON_SOURCE
# On Windows, all code using Python has to link to the Python
# import library.
#
# On *nix we never link libboost_python to libpython. When
# extending Python, all Python symbols are provided by the
# Python interpreter executable. When embedding Python, the
# client executable is expected to explicitly link to
# /python//python (the target representing libpython) itself.
#
# python_for_extensions is a target defined by Boost.Build to
# provide the Python include paths, and on Windows, the Python
# import library, as usage requirements.
[ cond [ python.configured ] : <library>/python//python_for_extensions ]
# we prevent building when there is no python available
# as it's not possible anyway, and to cause dependents to
# fail to build
[ unless [ python.configured ] : <build>no ]
<dependency>config-warning
alias install : config-warning ;
explicit install ;
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
[ cond $(is-py3) : <python>$(py3-version) ]
: # default build
<link>shared
: # usage requirements
<link>static:<define>BOOST_PYTHON_STATIC_LIB
<python-debugging>on:<define>BOOST_DEBUG_PYTHON
;
}
lib_boost_python ;
boost-install boost_python ;
if $(py3-version)
{
lib_boost_python yes ;
boost-install boost_python3 ;
}

140
config/__init__.py Normal file
View File

@@ -0,0 +1,140 @@
#
# 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)
from SCons.Variables import *
from SCons.Script import AddOption
from collections import OrderedDict
import platform
from . import ui
from . import cxx
from . import python
from . import numpy
from . import boost
def add_options(vars):
ui.add_option('-V', '--verbose', dest='verbose', action='store_true', help='verbose mode: print full commands.')
ui.add_option('--no-numpy', dest='numpy', action='store_false', help='do not attempt to build NumPy bindings.')
python.add_options(vars)
numpy.add_options(vars)
boost.add_options(vars)
vars.Add('CXX')
vars.Add('CPPPATH', converter=lambda v:v.split())
vars.Add('CCFLAGS', converter=lambda v:v.split())
vars.Add('CXXFLAGS', converter=lambda v:v.split())
vars.Add('LIBPATH', converter=lambda v:v.split())
vars.Add('LIBS', converter=lambda v:v.split())
vars.Add('PYTHON')
vars.Add('PYTHONLIBS')
vars.Add('prefix')
vars.Add('boostbook_prefix')
vars.Add('CXX11')
vars.Add('NUMPY')
vars.Add('NUMPY_CPPPATH', converter=lambda v:v.split())
ui.add_variable(vars, ("arch", "target architeture", platform.machine()))
ui.add_variable(vars, ("toolchain", "toolchain to use", 'gcc'))
ui.add_variable(vars, ListVariable("variant", "Build configuration", "release", ["release", "debug", "profile"]))
ui.add_variable(vars, ListVariable("link", "Library linking", "dynamic", ["static", "dynamic"]))
ui.add_variable(vars, ListVariable("threading", "Multi-threading support", "multi", ["single", "multi"]))
ui.add_variable(vars, EnumVariable("layout", "Layout of library names and header locations", "versioned", ["versioned", "system"]))
ui.add_variable(vars, PathVariable("stagedir", "If --stage is passed install only compiled library files in this location", "stage", PathVariable.PathAccept))
ui.add_variable(vars, PathVariable("prefix", "Install prefix", "/usr/local", PathVariable.PathAccept))
def get_checks(env):
checks = OrderedDict()
checks['cxx'] = cxx.check
checks['python'] = python.check
if env.GetOption('numpy') is not False:
checks['numpy'] = numpy.check
else:
env['NUMPY'] = False
checks['boost'] = boost.check
return checks
def set_property(env, **kw):
from toolchains.gcc import features as gcc_features
from toolchains.msvc import features as msvc_features
if 'gcc' in env['TOOLS']: features = gcc_features
elif 'msvc' in env['TOOLS']: features = msvc_features
else: raise Error('unknown toolchain')
features.init_once(env)
for (prop,value) in kw.items():
getattr(features, prop, lambda x, y : None)(env, value)
env[prop.upper()] = value
def boost_suffix(env):
suffix = str()
if env["layout"] == "versioned":
if "gcc" in env["TOOLS"]:
if env['CXX'] in ('clang', 'clang++'):
suffix += "-clang" + "".join(env["CXXVERSION"].split(".")[0:2])
else: # assume g++
suffix += "-gcc" + "".join(env["CXXVERSION"].split(".")[0:2])
if env["THREADING"] == "multi":
suffix += "-mt"
if env["DEBUG"]:
suffix += "-d"
if env["layout"] == "versioned":
suffix += "-" + "_".join(env["BPL_VERSION"].split("."))
return suffix
def prepare_build_dir(env):
vars = {}
env["boost_suffix"] = boost_suffix
build_dir="bin.SCons"
# FIXME: Support 'toolchain' variable properly.
# For now, we simply check whether $CXX refers to clang or gcc.
if "gcc" in env["TOOLS"]:
if env['CXX'] in ('clang', 'clang++'):
build_dir+="/clang-%s"%env["CXXVERSION"]
else: # assume g++
build_dir+="/gcc-%s"%env["CXXVERSION"]
default_cxxflags = ['-ftemplate-depth-128', '-Wall', '-g', '-O2']
vars['CXXFLAGS'] = env.get('CXXFLAGS', default_cxxflags)
elif "msvc" in env["TOOLS"]:
build_dir+="/msvc-%s"%env["MSVS_VERSION"]
vars['BOOST_BUILD_DIR'] = build_dir
vars['BOOST_SUFFIX'] = "${boost_suffix(__env__)}"
env.Replace(**vars)
return build_dir
def variants(env):
env.Prepend(CPPPATH = "#/include", CPPDEFINES = ["BOOST_ALL_NO_LIB=1"])
set_property(env, architecture = env['TARGET_ARCH'])
for variant in env["variant"]:
e = env.Clone()
e["current_variant"] = variant
set_property(env, profile = False)
if variant == "release":
set_property(e, optimize = "speed", debug = False)
elif variant == "debug":
set_property(e, optimize = "no", debug = True)
elif variant == "profile":
set_property(e, optimize = "speed", profile = True, debug = True)
for linking in env["link"]:
e["linking"] = linking
if linking == "dynamic":
e["LINK_DYNAMIC"] = True
else:
e["LINK_DYNAMIC"] = False
for threading in e["threading"]:
e["current_threading"] = threading
set_property(e, threading = threading)
yield e

45
config/boost.py Normal file
View File

@@ -0,0 +1,45 @@
#
# 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)
from . import ui
import os
def add_options(vars):
ui.add_option("--boost-prefix", dest="boost_prefix", type="string", nargs=1, action="store",
metavar="DIR", default=os.environ.get("BOOST_DIR"),
help="prefix for Boost libraries; should have 'include' and 'lib' subdirectories, 'boost' and 'stage\\lib' subdirectories on Windows")
ui.add_option("--boost-include", dest="boost_include", type="string", nargs=1, action="store",
metavar="DIR", help="location of Boost header files")
ui.add_option("--boostbook-prefix", dest="boostbook_prefix", type="string",
nargs=1, action="store",
metavar="DIR", default="/usr/share/boostbook",
help="prefix for BoostBook stylesheets")
def check(context):
boost_source_file = r"#include <boost/config.hpp>"
context.Message('Checking for Boost...')
boost_prefix = context.env.GetOption('boost_prefix')
boost_include = context.env.GetOption('boost_include')
boostbook_prefix = context.env.GetOption('boostbook_prefix')
incpath=None
if boost_include:
incpath=boost_include
elif boost_prefix:
incpath=boost_prefix
if incpath:
context.env.AppendUnique(CPPPATH=[incpath])
if not context.TryCompile(boost_source_file, '.cpp'):
context.Result(0)
return False
context.env.AppendUnique(boostbook_prefix=boostbook_prefix)
context.Result(1)
return True

30
config/cxx.py Normal file
View File

@@ -0,0 +1,30 @@
#
# 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)
from . import ui
import os
def add_options(vars):
pass
def check(context):
source = r"""#if __cplusplus < 201103L
#error no C++11
#endif"""
context.Message('Checking for C++11 support...')
if not context.TryCompile(source, '.cpp'):
context.env['CXX11'] = False
context.Result(0)
else:
context.env['CXX11'] = True
context.Result(1)
return True

86
config/numpy.py Normal file
View File

@@ -0,0 +1,86 @@
#
# 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)
from . import ui
from contextlib import contextmanager
@contextmanager
def saved(context):
save_cpppath = context.env.get('CPPPATH', [])
save_libs = context.env.get('LIBS', [])
yield context
context.env.Replace(LIBS=save_libs)
context.env.Replace(CPPPATH=save_cpppath)
def add_options(vars):
pass
def check(context):
numpy_source_file = r"""
// If defined, enforces linking againg PythonXXd.lib, which
// is usually not included in Python environments.
#undef _DEBUG
#include "Python.h"
#include "numpy/arrayobject.h"
#if PY_VERSION_HEX >= 0x03000000
void *initialize() { import_array();}
#else
void initialize() { import_array();}
#endif
int main()
{
int result = 0;
Py_Initialize();
initialize();
if (PyErr_Occurred())
{
result = 1;
}
else
{
npy_intp dims = 2;
PyObject * a = PyArray_SimpleNew(1, &dims, NPY_INT);
if (!a) result = 1;
Py_DECREF(a);
}
Py_Finalize();
return result;
}
"""
import platform
import subprocess
import re, os
def check_python(cmd):
try:
return True, subprocess.check_output([python, '-c', cmd]).strip()
except subprocess.CalledProcessError as e:
return False, e
context.Message('Checking for NumPy...')
with saved(context):
python = context.env['PYTHON']
result, numpy_incpath = check_python('import numpy; print(numpy.get_include())')
if result:
context.env.AppendUnique(CPPPATH=numpy_incpath)
context.env.AppendUnique(LIBS=context.env['PYTHONLIBS'])
result, output = context.TryRun(numpy_source_file,'.cpp')
if not result:
context.Result(0)
return False
context.env['NUMPY'] = True
context.env['NUMPY_CPPPATH'] = numpy_incpath
context.Result(1)
return True

98
config/python.py Normal file
View File

@@ -0,0 +1,98 @@
#
# 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)
from . import ui
def add_options(vars):
ui.add_option('--python', help='the python executable')
def check(context):
python_source_file = r"""
// If defined, enforces linking againg PythonXXd.lib, which
// is usually not included in Python environments.
#undef _DEBUG
#include "Python.h"
int main()
{
Py_Initialize();
Py_Finalize();
return 0;
}
"""
import platform
import subprocess
import re, os
def check_python(cmd):
return subprocess.check_output([python, '-c', cmd]).strip()
def check_sysconfig(cmd):
r = check_python('import distutils.sysconfig as c; print(c.%s)'%cmd)
return r if r != 'None' else ''
context.Message('Checking for Python...')
python = context.env.GetOption('python') or 'python'
context.env['PYTHON'] = python
incpath = check_sysconfig('get_python_inc()')
context.env.AppendUnique(CPPPATH=[incpath])
if platform.system() == 'Windows':
version = check_python('import sys; print("%d%d"%sys.version_info[0:2])')
prefix = check_python('import sys; print(sys.prefix)')
libfile = os.path.join(prefix, 'libs', 'python%s.lib'%version)
libpath = os.path.join(prefix, 'libs')
lib = 'python%s'%version
context.env.AppendUnique(LIBS=[lib])
else:
libpath = check_sysconfig('get_config_var("LIBDIR")')
libfile = check_sysconfig('get_config_var("LIBRARY")')
match = re.search('(python.*)\.(a|so|dylib)', libfile)
lib = None
if match:
lib = match.group(1)
context.env.AppendUnique(PYTHONLIBS=[lib])
if match.group(2) == 'a':
flags = check_sysconfig('get_config_var("LINKFORSHARED")')
if flags is not None:
context.env.AppendUnique(LINKFLAGS=flags.split())
context.env.AppendUnique(LIBPATH=[libpath])
oldlibs = context.AppendLIBS([lib])
flags = check_sysconfig('get_config_var("MODLIBS")')
flags += ' ' + check_sysconfig('get_config_var("SHLIBS")')
flags = [f[2:] for f in flags.strip().split() if f.startswith('-l')]
if flags:
context.AppendLIBS([flags])
result = context.TryLink(python_source_file,'.cpp')
if not result and context.env['PLATFORM'] == 'darwin':
# Sometimes we need some extra stuff on Mac OS
frameworkDir = libpath # search up the libDir tree for the proper home for frameworks
while frameworkDir and frameworkDir != "/":
frameworkDir, d2 = os.path.split(frameworkDir)
if d2 == "Python.framework":
if not "Python" in os.listdir(os.path.join(frameworkDir, d2)):
context.Result(0)
print((
"Expected to find Python in framework directory %s, but it isn't there"
% frameworkDir))
return False
break
context.env.AppendUnique(LINKFLAGS="-F%s" % frameworkDir)
result = context.TryLink(python_source_file,'.cpp')
if not result:
context.Result(0)
print("Cannot link program with Python.")
return False
if context.env['PLATFORM'] == 'darwin':
context.env['LDMODULESUFFIX'] = '.so'
context.Result(1)
context.SetLIBS(oldlibs)
context.env.AppendUnique(PYTHONLIBS=[lib] + flags)
return True

View File

@@ -0,0 +1,18 @@
#
# 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)
import traceback
def append_feature_flag(env, **kw):
stack = traceback.extract_stack(limit = 3)
feature = stack[0][2].upper()
for (key, val) in kw.items():
feature_var = feature + "_" + key
env.AppendUnique(**{ key : "$" + feature_var })
env[feature_var] = val

55
config/toolchains/gcc.py Normal file
View File

@@ -0,0 +1,55 @@
#
# 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)
from . import append_feature_flag
class features:
@classmethod
def init_once(cls, env):
pass
@staticmethod
def architecture(env, arch):
if arch:
flag = {'x86' : '-m32',
'x86_64' : '-m64',}.get(arch)
if flag:
append_feature_flag(env, CCFLAGS = flag)
@staticmethod
def optimize(env, optimize):
if not optimize or optimize == "no":
append_feature_flag(env, CCFLAGS = "-O0 -fno-inline")
elif optimize == "speed":
append_feature_flag(env, CCFLAGS = "-O3 -finline-functions -Wno-inline")
elif optimize == "space":
append_feature_flag(env, CCFLAGS = "-Os")
else:
append_feature_flag(env, CCFLAGS = "")
@staticmethod
def profile(env, profile):
if profile:
append_feature_flag(env, CCFLAGS = "-pg", LINKFLAGS = "-pg")
else:
append_feature_flag(env, CCFLAGS = "", LINKFLAGS = "")
@staticmethod
def threading(env, threading):
if threading == "multi":
append_feature_flag(env, CCFLAGS = "-pthread", LINKFLAGS = "-pthread")
else:
append_feature_flag(env, CCFLAGS = "", LINKFLAGS = "")
@staticmethod
def debug(env, debug):
if debug:
append_feature_flag(env, CCFLAGS = "-g", CPPDEFINES = [])
else:
append_feature_flag(env, CCFLAGS = "", CPPDEFINES = "NDEBUG")

57
config/toolchains/msvc.py Normal file
View File

@@ -0,0 +1,57 @@
#
# 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)
from . import append_feature_flag
class features:
@classmethod
def init_once(cls, env):
env.AppendUnique(CCFLAGS = ['-TP', '/Z7', '/W3' ,'/GR', '/MDd', '/Zc:forScope', '/Zc:wchar_t', '/wd4675', '/EHs'])
env.AppendUnique(LINKFLAGS = ['/subsystem:console'])
@staticmethod
def architecture(env, arch):
if arch:
flag = {'x86' : '/MACHINE:X86',
'x86_64' : '/MACHINE:X64',}.get(arch)
if flag:
append_feature_flag(env, LINKFLAGS = flag)
@staticmethod
def optimize(env, optimize):
#if not optimize or optimize == "no":
# append_feature_flag(env, CCFLAGS = "-O0 -fno-inline")
#elif optimize == "speed":
# append_feature_flag(env, CCFLAGS = "-O3 -finline-functions -Wno-inline")
#elif optimize == "space":
# append_feature_flag(env, CCFLAGS = "-Os")
#else:
append_feature_flag(env, CCFLAGS = "")
@staticmethod
def profile(env, profile):
#if profile:
# append_feature_flag(env, CCFLAGS = "-pg", LINKFLAGS = "-pg")
#else:
append_feature_flag(env, CCFLAGS = "", LINKFLAGS = "")
@staticmethod
def threading(env, threading):
#if threading == "multi":
# append_feature_flag(env, CCFLAGS = "/MT")
#else:
# append_feature_flag(env, CCFLAGS = "", LINKFLAGS = "")
pass
@staticmethod
def debug(env, debug):
#if debug:
# append_feature_flag(env, CCFLAGS = "-g", CPPDEFINES = [])
#else:
append_feature_flag(env, CCFLAGS = "", CPPDEFINES = "NDEBUG")

44
config/tools/clang.py Normal file
View File

@@ -0,0 +1,44 @@
#
# 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)
# Based on SCons/Tool/gcc.py
import os
import re
import subprocess
import SCons.Util
import SCons.Tool.cc
compilers = ['clang']
def generate(env):
"""Add Builders and construction variables for clang to an Environment."""
SCons.Tool.cc.generate(env)
env['CC'] = env.Detect(compilers) or 'clang'
if env['PLATFORM'] in ['cygwin', 'win32']:
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
else:
env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC')
# determine compiler version
if env['CC']:
#pipe = SCons.Action._subproc(env, [env['CC'], '-dumpversion'],
pipe = SCons.Action._subproc(env, [env['CC'], '--version'],
stdin = 'devnull',
stderr = 'devnull',
stdout = subprocess.PIPE)
if pipe.wait() != 0: return
# clang -dumpversion is of no use
line = pipe.stdout.readline()
match = re.search(r'clang +version +([0-9]+(?:\.[0-9]+)+)', line)
if match:
env['CCVERSION'] = match.group(1)
def exists(env):
return env.Detect(compilers)

75
config/tools/doc.py Normal file
View File

@@ -0,0 +1,75 @@
#
# 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)
from SCons.Script import AddOption, Flatten
from SCons.Script import Builder
from SCons.Action import Action
from SCons.Defaults import Copy
from SCons.Script import *
from subprocess import check_output, STDOUT, CalledProcessError
import sys
import os
def QuickBook(env, target, source, dependencies=[]):
"""Compile a QuickBook document to BoostBook."""
for d in dependencies:
env.Depends(target, d)
env.Command(target, source, 'quickbook --input-file=$SOURCE --output-file=$TARGET')
def BoostBook(env, target, source, resources=[], args=[]):
"""Compile a BoostBook document to DocBook."""
bb_prefix = env.GetOption('boostbook_prefix')
stylesheet = bb_prefix + '/xsl/docbook.xsl'
env.Command(target, source,
'xsltproc {} -o $TARGET {} $SOURCE'.format(' '.join(args), stylesheet))
def BoostHTML(env, target, source, resources=[], args=[]):
"""Compile a DocBook document to HTML."""
bb_prefix = env.GetOption('boostbook_prefix')
stylesheet = bb_prefix + '/xsl/html.xsl'
env.Command(target, source,
'xsltproc {} -o $TARGET/ {} $SOURCE'.format(' '.join(args), stylesheet))
prefix=Dir('.').path
for r in resources:
r = File(r).path[len(prefix)+1:]
env.Depends(target, target + r)
env.Command(target + r, r, Copy('$TARGET', '$SOURCE'))
def BoostRST(env, target, source, resources=[]):
"""Compile an RST document to HTML."""
prefix=Dir('.').path
for r in resources:
r = File(r).path[len(prefix)+1:]
env.Depends('html/' + r, r)
env.Command('html/' + r, r, Copy('$TARGET', '$SOURCE'))
env.Command(target, source,
'rst2html --link-stylesheet --traceback --trim-footnote-reference-space --footnote-references=superscript --stylesheet=rst.css $SOURCE $TARGET')
def BoostSphinx(env, target, source):
env.Sphinx(target, source)
def exists(env):
return True
def generate(env):
env.AddMethod(QuickBook)
env.AddMethod(BoostBook)
env.AddMethod(BoostHTML)
env.AddMethod(BoostRST)
env.AddMethod(BoostSphinx)

85
config/tools/libs.py Normal file
View File

@@ -0,0 +1,85 @@
#
# 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)
from SCons.Script import AddOption, COMMAND_LINE_TARGETS, BUILD_TARGETS
import distutils.sysconfig
import platform
def BoostLibrary(env, lib, sources, make_aliases = True, **kw):
if env["LINK_DYNAMIC"]:
lib_node = env.SharedLibrary("boost_" + lib + env["BOOST_SUFFIX"], sources, **kw)
else:
lib_node = env.StaticLibrary("boost_" + lib + env["BOOST_SUFFIX"], sources, **kw)
if make_aliases:
if env.GetOption("stage"):
env.Alias(lib, env.Install(env.Dir("$stagedir", "#"), lib_node))
env.Default(env.Alias(lib, lib_node))
if env.GetOption("install"):
env.Alias(lib, env.Install("$prefix/lib", lib_node))
env.Alias(lib, env.Install('$prefix/include/boost', '#/include/boost/python'))
env.Alias(lib, env.Install('$prefix/include/boost', '#/include/boost/python.hpp'))
return lib_node
def BoostUseLib(env, lib):
build_dir = env.Dir('$BOOST_CURRENT_VARIANT_DIR/src')
env.AppendUnique(LIBPATH = [build_dir],
LIBS = ["boost_" + lib + env["BOOST_SUFFIX"]])
if env.get("BOOST_TEST"):
env.AppendUnique(RPATH = [build_dir])
if platform.system() == 'Windows':
env.PrependENVPath('PATH', build_dir.abspath)
else:
env.PrependENVPath('LD_LIBRARY_PATH', build_dir.abspath)
def PythonExtension(env, lib, sources, **kw):
if env["LINK_DYNAMIC"]:
ext = env.SharedLibrary(lib, sources, SHLIBPREFIX='', SHLIBSUFFIX=distutils.sysconfig.get_config_var("SO"), **kw)
return ext
def boost_copy_func(dest, source, env):
import os, stat, shutil
if os.path.isdir(source):
if os.path.exists(dest):
if not os.path.isdir(dest):
raise SCons.Errors.UserError, "cannot overwrite non-directory `%s' with a directory `%s'" % (str(dest), str(source))
else:
os.makedirs(dest)
for file in os.listdir(source):
if file == ".svn": continue
boost_copy_func(os.path.join(dest, file), os.path.join(source, file), env)
else:
shutil.copy2(source, dest)
st = os.stat(source)
os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
return 0
def exists(env):
return True
def generate(env):
env.AddMethod(BoostLibrary)
env.AddMethod(BoostUseLib)
env.AddMethod(PythonExtension)
env.Replace(
INSTALL = boost_copy_func,
BOOST_CURRENT_VARIANT_DIR = "#/$BOOST_BUILD_DIR/$current_variant/$linking/threading-$current_threading"
)
AddOption('--stage', dest='stage', action="store_true")
AddOption('--install', dest='install', action="store_true")

View File

@@ -0,0 +1,592 @@
"""SCons.Tool.spinx4scons
Tool-specific initialization for the Sphinx document build system.
There normally shouldn't be any need to import this module directly.
It will usually be imported through the generic SCons.Tool.Tool()
selection method.
It should be placed in e.g. ~/site_scons/site_tools/sphinx4scons/
directory. Then it may be loaded by placing
sphinx = Tool('sphinx4scons')
sphinx(env)
in your SConstruct file.
For further details, please see the SCons documentation on how to
install and enable custom tools.
"""
#
# This package is provided under the Expat license
#
# Copyright (c) 2012 Orlando Wingbrant
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
__author__ = "Orlando Wingbrant"
__email__ = "orlando@widesite.org"
__url__ = "https://bitbucket.org/wingbrant/sphinx4scons"
__license__ = "Expat license"
import SCons.Action
import SCons.Builder
import SCons.Defaults
import SCons.Util
import SCons.Node.FS
import os
from sphinx.util.matching import patfilter, compile_matchers
from sphinx.util.osutil import make_filename
class ToolSphinxWarning(SCons.Warnings.Warning):
pass
class SphinxBuilderNotFound(ToolSphinxWarning):
pass
SCons.Warnings.enableWarningClass(ToolSphinxWarning)
def exists(env):
return _detect(env)
def _detect(env):
"""Try to detect the sphinx-build script."""
try:
return env['SPHINXBUILD']
except KeyError:
pass
sphinx = env.WhereIs('sphinx-build')
if sphinx:
return sphinx
raise SCons.Errors.StopError(
SphinxBuilderNotFound,
"Could not detect sphinx-build script")
return None
def generate(env):
"""Add Builders and construction variables to the Environment."""
env['SPHINXBUILD'] = _detect(env)
sphinx = _create_sphinx_builder(env)
env.SetDefault(
# Additional command-line flags
SPHINXFLAGS = '',
# Tag definitions, each entry will appear on the command line preceded by -t
SPHINXTAGS = [],
# Directory for doctrees
SPHINXDOCTREE = '',
# Path to sphinx configuration file
SPHINXCONFIG = '',
# Config file override settings, each entry will be preceded by -D
SPHINXSETTINGS = {},
# Default sphinx builder,
SPHINXBUILDER = 'html',
# Sphinx command
SPHINXCOM = "$SPHINXBUILD $_SPHINXOPTIONS ${SOURCE.attributes.root} ${TARGET.attributes.root}",
# Alternate console output when building sphinx documents
SPHINXCOMSTR = ""
)
try:
env.AddMethod(Sphinx, "Sphinx")
except AttributeError:
# Looks like we use a pre-0.98 version of SCons...
from SCons.Script.SConscript import SConsEnvironment
SConsEnvironment.Sphinx = Sphinx
def Sphinx(env, target, source, **kw):
"""A pseudo-builder wrapper for the sphinx builder."""
builder = env['BUILDERS']['Sphinx4Scons']
env_kw = env.Override(kw)
options = _get_sphinxoptions(env_kw, target, source)
output = builder(env, target, source, _SPHINXOPTIONS=options, **kw)
return output
def _get_sphinxoptions(env, target, source):
"""Concatenates all the options for the sphinx command line."""
options = []
builder = _get_sphinxbuilder(env)
options.append("-b %s" % env.subst(builder, target=target, source=source))
flags = env.get('options', env.get('SPHINXFLAGS', ''))
options.append(env.subst(flags, target=target, source=source))
tags = env.get('tags', env.get('SPHINXTAGS', None))
if tags is not None:
if not SCons.SCons.Util.is_List(tags):
tags = [tags]
for tag in tags:
if tag != '':
tag = env.subst(tag, target=target, source=source)
options.append("-t %s" % tag)
settings = env.get('settings', env.get('SPHINXSETTINGS', None))
if settings is not None:
if not SCons.SCons.Util.is_Dict(settings):
raise TypeError('SPHINXSETTINGS and/or settings argument must be a dictionary')
for key, value in settings.iteritems():
if value != '':
value = env.subst(value, target=target, source=source)
options.append('-D "%s=%s"' % (key, value))
doctree = env.get('doctree', env.get("SPHINXDOCTREE", None))
if isinstance(doctree, SCons.Node.FS.Dir):
options.append("-d %s" % doctree.get_abspath())
elif doctree is not None and doctree != '':
doctree = env.subst(doctree, target=target, source=source)
options.append("-d %s" % env.Dir(doctree).get_abspath())
config = _get_sphinxconfig_path(env, None)
if config is not None and config != '':
config = env.subst(config, target=target, source=source)
options.append("-c %s" % env.Dir(config).File('conf.py').rfile().dir.get_abspath())
return " ".join(options)
def _create_sphinx_builder(env):
try:
sphinx = env['BUILDERS']['Sphinx4Scons']
except KeyError:
fs = SCons.Node.FS.get_default_fs()
sphinx_com = SCons.Action.Action('$SPHINXCOM', '$SPHINXCOMSTR')
sphinx = SCons.Builder.Builder(action=sphinx_com,
emitter=sphinx_emitter,
target_factory=fs.Dir,
source_factory=fs.Dir
)
env['BUILDERS']['Sphinx4Scons'] = sphinx
return sphinx
def sphinx_emitter(target, source, env):
target[0].must_be_same(SCons.Node.FS.Dir)
targetnode = target[0]
source[0].must_be_same(SCons.Node.FS.Dir)
srcnode = source[0]
configdir = _get_sphinxconfig_path(env, None)
if not configdir:
confignode = srcnode
else:
confignode = env.Dir(configdir)
srcinfo = SourceInfo(srcnode, confignode, env)
targets, sources = _get_emissions(env, target, srcinfo)
env.Clean(targets, target[0])
return targets, sources
def sphinx_path(os_path):
"""Create sphinx-style path from os-style path."""
return os_path.replace(os.sep, "/")
def os_path(sphinx_path):
"""Create os-style path from sphinx-style path."""
return sphinx_path.replace("/", os.sep)
class SourceInfo(object):
"""
Data container for all different kinds of source files used in
a sphinx project.
"""
def __init__(self, srcnode, confignode, env):
self.confignode = confignode
self.config = self._get_config(self.confignode, env)
self.templates = self._get_templates(self.confignode, self.config)
self.statics = self._get_statics(self.confignode, self.config)
self.srcnode = srcnode
self.sources = self._get_sources(self.srcnode, self.config)
self.srcroot = srcnode
if not srcnode.duplicate:
self.srcroot = srcnode.srcnode().rdir()
def _get_config(self, confignode, env):
config = {}
execfile(confignode.File('conf.py').rfile().get_abspath(), config)
return config
def _get_templates(self, confignode, config):
"""Returns template files defined in the project."""
templates = []
for path in config.get('templates_path', []):
# Check if path is dir or file.
# We can't use FS.Entry since that will create nodes, and
# these nodes don't know about the source tree and will
# get disambiguated to files even if they are directories in the
# source tree.
p = confignode.File('conf.py').rfile().dir.srcnode().get_abspath()
p = os.path.join(p, os_path(path))
if os.path.isfile(p):
templates.append(confignode.File(path))
elif os.path.isdir(p):
node = confignode.Dir(path)
for root, dirs, files in os.walk(p):
mydir = node.Dir(os.path.relpath(root, p))
templates += [mydir.File(f) for f in files]
return templates
def _get_statics(self, confignode, config):
"""Returns static files, filtered through exclude_patterns."""
statics = []
matchers = compile_matchers(config.get('exclude_patterns', []))
for path in config.get('html_static_path', []):
# Check _get_templates() why we use this construction.
p = confignode.File('conf.py').rfile().dir.srcnode().get_abspath()
p = os.path.join(p, os_path(path))
if os.path.isfile(p):
statics.append(confignode.File(path))
elif os.path.isdir(p):
node = confignode.Dir(path)
for root, dirs, files in os.walk(p):
relpath = os.path.relpath(root, p)
for entry in [d for d in dirs if
self._anymatch(matchers,
sphinx_path(os.path.join(relpath, d)))]:
dirs.remove(entry)
statics += [node.File(os_path(f)) for f in
self._exclude(matchers,
[sphinx_path(os.path.join(relpath, name))
for name in files])]
return statics
def _get_sources(self, srcnode, config):
"""Returns all source files in the project filtered through exclude_patterns."""
suffix = config.get('source_suffix', '.rst')
matchers = compile_matchers(config.get('exclude_patterns', []))
srcfiles = []
scannode = srcnode.srcnode().rdir()
for root, dirs, files in os.walk(scannode.get_abspath()):
relpath = os.path.relpath(root, scannode.get_abspath())
for entry in [d for d in dirs if
self._anymatch(matchers,
sphinx_path(os.path.join(relpath, d)))]:
dirs.remove(entry)
srcfiles += [srcnode.File(os_path(f)) for f in
self._exclude(matchers,
[sphinx_path(os.path.join(relpath, name))
for name in files if name.endswith(suffix)])]
return srcfiles
def _exclude(self, matchers, items):
result = items
for matcher in matchers:
result = filter(lambda x: not matcher(x), result)
return result
def _anymatch(self, matchers, item):
for matcher in matchers:
if matcher(item):
return True
return False
def _get_sphinxconfig_path(env, default):
path = env.get('config', env.get('SPHINXCONFIG', None))
if path is None or path == '':
path = default
return path
def _get_emissions(env, target, srcinfo):
targets = []
sources = []
builder = _get_sphinxbuilder(env)
if builder == 'changes':
targets, sources = _get_changes_emissions(env, target, srcinfo)
if builder == 'devhelp':
targets, sources = _get_help_emissions(env, target, srcinfo,
['.devhelp.gz'])
elif builder == 'dirhtml':
targets, sources = _get_dirhtml_emissions(env, target, srcinfo)
elif builder == 'doctest':
targets, sources = _get_doctest_emissions(env, target, srcinfo)
elif builder == 'epub':
targets, sources = _get_epub_emissions(env, target, srcinfo)
elif builder == 'html':
targets, sources = _get_serialize_emissions(env, target, srcinfo)
elif builder == 'htmlhelp':
targets, sources = _get_help_emissions(env, target, srcinfo,
['.hhp'], 'htmlhelp_basename')
elif builder == 'gettext':
targets, sources = _get_gettext_emissions(env, target, srcinfo)
elif builder == 'json':
targets, sources = _get_serialize_emissions(env, target, srcinfo,
'.fjson',
['globalcontext.json',
'searchindex.json',
'self.environment.pickle'])
elif builder == 'latex':
targets, sources = _get_latex_emissions(env, target, srcinfo)
elif builder == 'linkcheck':
targets, sources = _get_linkcheck_emissions(env, target, srcinfo)
elif builder == 'man':
targets, sources = _get_man_emissions(env, target, srcinfo)
elif builder == 'pickle':
targets, sources = _get_serialize_emissions(env, target, srcinfo,
'.fpickle',
['globalcontext.pickle',
'searchindex.pickle',
'environment.pickle'])
elif builder == 'qthelp':
targets, sources = _get_help_emissions(env, target, srcinfo,
['.qhp', '.qhcp'])
elif builder == 'singlehtml':
targets, sources = _get_singlehtml_emissions(env, target, srcinfo)
elif builder == 'texinfo':
targets, sources = _get_texinfo_emissions(env, target, srcinfo)
elif builder == 'text':
targets, sources = _get_text_emissions(env, target, srcinfo)
sources.append(srcinfo.confignode.File('conf.py'))
for s in sources:
s.attributes.root = srcinfo.srcroot
for t in targets:
t.attributes.root = target[0]
return targets, sources
def _get_sphinxbuilder(env):
builder = env.get('builder', env["SPHINXBUILDER"])
if builder is None or builder == '':
raise SCons.Errors.UserError(("Missing construction variable " +
"SPHINXBUILDER or variable is empty."))
return builder
def _get_changes_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [target[0].File("changes.html")]
return targets, sources
def _get_dirhtml_emissions(env, target, srcinfo):
suffix = srcinfo.config.get('html_file_suffix', ".html")
def get_outfilename(pagename):
pagename = os.path.splitext(pagename)[0]
#Special treatment of files named "index". Don't create directory.
if pagename == 'index' or pagename.endswith(os.sep + 'index'):
outfilename = pagename + suffix
else:
outfilename = os.path.join(pagename, 'index' + suffix)
return outfilename
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
targets = []
for s in srcinfo.sources:
t = os.path.relpath(str(s), str(srcinfo.srcroot))
targets.append(target[0].File(get_outfilename(t)))
for key in srcinfo.config.get('html_additional_pages', {}):
t = target[0].File(get_outfilename(key))
targets.append(t)
return targets, sources
def _get_doctest_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [target[0].File("output.txt")]
return targets, sources
def _get_epub_emissions(env, target, srcinfo):
epubPreFiles = srcinfo.config.get('epub_pre_files', [])
epubPostFiles = srcinfo.config.get('epub_post_files', [])
epubCover = srcinfo.config.get('epub_cover', (None, None))
sources = []
sources.extend(srcinfo.sources)
sources.extend([srcinfo.srcroot.File(os_path(f[0])) for f in epubPreFiles])
sources.extend([srcinfo.srcroot.File(os_path(f[0])) for f in epubPostFiles])
if not (epubCover[0] is None or epubCover[0] == ''):
sources.append(srcinfo.srcroot.File(os_path(epubCover[0])))
if not (epubCover[1] is None or epubCover[1] == ''):
sources.append(srcinfo.srcroot.File(os_path(epubCover[1])))
t = srcinfo.config.get('epub_basename',
srcinfo.config.get('project',
'Python'))
targets = [target[0].File("%s.epub" % make_filename(t))]
return targets, sources
def _get_gettext_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [os.path.relpath(str(s), str(srcinfo.srcroot)) for s in sources]
targets = [os.path.splitext(t)[0] for t in targets]
targets = set([t.split(os.sep)[0] for t in targets])
targets = [target[0].File(t + ".pot") for t in targets]
return targets, sources
def _get_help_emissions(env, target, srcinfo, suffixes, basenameConfigKey='project'):
basename = make_filename(
srcinfo.config.get(basenameConfigKey, srcinfo.config['project']))
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
targets = [target[0].File(basename + s) for s in suffixes]
return targets, sources
def _get_latex_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = map(lambda x: target[0].File(os_path(x[1])),
srcinfo.config.get('latex_documents'))
return targets, sources
def _get_linkcheck_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = [target[0].File("output.txt")]
return targets, sources
def _get_man_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = map(lambda x: target[0].File(os_path("%s.%s" % (x[1], x[4]))),
srcinfo.config.get('man_pages'))
return targets, sources
def _get_serialize_emissions(env, target, srcinfo, suffix=None, extrafiles=[]):
if suffix is None:
suffix = srcinfo.config.get('html_file_suffix', '.html')
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
targets = []
for s in srcinfo.sources:
t = os.path.splitext(str(s))[0] + suffix
t = os.path.relpath(t, str(srcinfo.srcroot))
targets.append(t)
for key in srcinfo.config.get('html_additional_pages', {}):
targets.append(os_path("%s%s" % (key, suffix)))
targets.extend(extrafiles)
targets = [target[0].File(t) for t in targets]
return targets, sources
def _get_singlehtml_emissions(env, target, srcinfo):
suffix = srcinfo.config.get('html_file_suffix', ".html")
sources = []
sources.extend(srcinfo.sources)
sources.extend(srcinfo.templates)
sources.extend(srcinfo.statics)
t = os.path.relpath(srcinfo.config['master_doc'] + suffix,
str(srcinfo.srcroot))
targets = [target[0].File(t)]
return targets, sources
def _get_texinfo_emissions(env, target, srcinfo):
suffix = srcinfo.config.get('source_suffix', '.rst')
sources = []
sources.extend(srcinfo.sources)
sources.extend(map(lambda x: source[0].File(os_path(x + suffix)),
srcinfo.config.get('texinfo_appendices', [])))
targets = map(lambda x: target[0].File(os_path("%s.texi" % x[1])),
srcinfo.config.get('texinfo_documents'))
return targets, sources
def _get_text_emissions(env, target, srcinfo):
sources = []
sources.extend(srcinfo.sources)
targets = []
for s in sources:
t = os.path.relpath(str(s), str(srcinfo.srcroot))
t = os.path.splitext(t)[0] + ".txt"
targets.append(target[0].File(t))
return targets, sources

123
config/tools/tests.py Normal file
View File

@@ -0,0 +1,123 @@
#
# 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)
from SCons.Script import AddOption, Flatten
from SCons.Script import Builder
from SCons.Action import Action
from subprocess import check_output, STDOUT, CalledProcessError
import sys
import os
def BoostCompileTest(env, test, source = None, **kw):
def gen_result(target, source, env=env):
target_file = target[0].abspath
result_file = os.path.splitext(target_file)[0] + '.result'
if sys.stdout.isatty():
env['RESULT']='\033[92mPASS\033[0m'
else:
env['RESULT']='PASS'
with open(result_file, 'w+') as result:
result.write('Result: {}\n'.format('pass'))
obj = env.Object(test, source if source is not None else test + '.cpp')
env.AddPostAction(obj, Action(gen_result, cmdstr=None))
env.AddPostAction(obj, Action('@echo $RESULT'))
return obj
def BoostRun(env, prog, target, command = '$SOURCE'):
def call(target, source, env=env):
cmd = env.subst(command, target=target, source=source)
result_file = env.subst('$TARGET', target=target)
output=''
try:
output=check_output(cmd, stderr=STDOUT, shell=True, env=env['ENV'])
success=True
except CalledProcessError as e:
output=e.output
success=False
with open(result_file, 'w+') as result:
result.write('Result: {}\n'.format(success and 'pass' or 'fail'))
result.write('Output: {}\n'.format(output))
if sys.stdout.isatty():
env['RESULT']=success and '\033[92mPASS\033[0m' or '\033[91mFAIL\033[0m'
else:
env['RESULT']=success and 'PASS' or 'FAIL'
testcomstr = env.get('TESTCOMSTR')
if testcomstr:
run = env.Command(target, prog, Action(call, cmdstr=testcomstr))
else:
run = env.Command(target, prog, Action(call, cmdstr=command))
env.AddPostAction(target, Action('@echo $RESULT'))
return run
def BoostRunPythonScript(env, script):
return env.BoostRun(env.File(script), script.replace('.py', '.result'), '"${PYTHON}" $SOURCE')
def BoostRunTest(env, test, source = None, command = '$SOURCE', command_sources = [], **kw):
test_prog = env.Program(test, (source is None) and (test + ".cpp") or source, **kw)
command += '> $TARGET'
run = env.BoostRun([test_prog, command_sources], test + '.result', command)
return run
def BoostRunTests(env, tests, **kw):
run = []
for test in Flatten(tests):
run += env.BoostRunTest(test, **kw)
return run
def BoostCompileTests(env, tests, **kw):
comp = []
for test in Flatten(tests):
comp += env.BoostCompileTest(test, **kw)
return comp
def BoostTestSummary(env, tests, **kw):
def print_summary(target, source, **kw):
results = tests
failures = [r for r in results
if r.get_path().endswith('.result') and not 'Result: pass' in r.get_contents()]
print('%s tests; %s pass; %s fails'%(len(results), len(results)-len(failures), len(failures)))
if failures:
print('For detailed failure reports, see:')
for f in failures:
print(f.get_path())
testsumcomstr = env.get('TESTSUMCOMSTR')
if testsumcomstr:
run = env.Command('summary', tests, Action(print_summary, cmdstr=testsumcomstr))
else:
run = env.Command('summary', tests, print_summary, cmdstr='')
def exists(env):
return True
def generate(env):
AddOption('--test', dest='test', action="store_true")
env.AddMethod(BoostCompileTest)
env.AddMethod(BoostRun)
env.AddMethod(BoostRunPythonScript)
env.AddMethod(BoostRunTest)
env.AddMethod(BoostRunTests)
env.AddMethod(BoostCompileTests)
env.AddMethod(BoostTestSummary)

96
config/ui.py Normal file
View File

@@ -0,0 +1,96 @@
#
# 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)
from SCons.Script import AddOption
import sys
variables=[] # remember 'public' variables
options=[]
def add_option(*args, **kwds):
"""Capture the help messages so we can produce a helpful usage text."""
options.append('{:25} {}'.format(', '.join(args), kwds.get('help', '')))
AddOption(*args, **kwds)
def add_variable(vars, var):
variables.append(var[0])
vars.Add(var)
def options_help(env):
return '\n '.join(options)
def variables_help(vars, env):
"""This is cloned from SCons' Variables.GenerateHelpText, to only report 'public' variables."""
opts = [o for o in vars.options if o.key in variables]
def format(opt):
if opt.key in env:
actual = env.subst('${%s}' % opt.key)
else:
actual = None
return vars.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
text = ''.join([f for f in map(format, opts) if f])
lines = [' %s'%l for l in text.split('\n')] # Add some indentation
return '\n'.join(lines)
def help(vars, env):
return """Usage: scons [--option...] [variable=value...] [target...]
available options:
{}
available variables:
{}
""".format(options_help(env), variables_help(vars, env))
def pretty_output(env):
colors = {}
colors['red'] = '\033[31m'
colors['green'] = '\033[32m'
colors['blue'] = '\033[34m'
colors['yellow'] = '\033[93m'
colors['Red'] = '\033[91m'
colors['Green'] = '\033[92m'
colors['Blue'] = '\033[94m'
colors['Purple'] = '\033[95m'
colors['Cyan'] = '\033[96m'
colors['end'] = '\033[0m'
#If the output is not a terminal, remove the colors
if not sys.stdout.isatty():
for key, value in colors.iteritems():
colors[key] = ''
compile_source_message = '{green}Compiling $TARGET{end}'.format(**colors)
compile_shared_source_message = '{green}Compiling $TARGET{end}'.format(**colors)
link_program_message = '{blue}Linking $TARGET{end}'.format(**colors)
link_library_message = '{blue}Linking $TARGET{end}'.format(**colors)
ranlib_library_message = '{blue}Ranlib $TARGET{end}'.format(**colors)
link_shared_library_message = '{blue}Linking $TARGET{end}'.format(**colors)
test_message = '{blue}Testing $SOURCE{end}'.format(**colors)
testsum_message = '{Blue}Test Summary{end}'.format(**colors)
env.Replace(CXXCOMSTR = compile_source_message,
CCCOMSTR = compile_source_message,
SHCCCOMSTR = compile_shared_source_message,
SHCXXCOMSTR = compile_shared_source_message,
ARCOMSTR = link_library_message,
RANLIBCOMSTR = ranlib_library_message,
SHLINKCOMSTR = link_shared_library_message,
LINKCOMSTR = link_program_message,
TESTCOMSTR = test_message,
TESTSUMCOMSTR = testsum_message)

View File

@@ -4,14 +4,10 @@
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import boostbook ;
import quickbook ;
import docutils ;
import os ;
path-constant here : . ;
path-constant images : html/images ;
project python/doc
: requirements
-<xsl:param>boost.defaults=Boost
@@ -21,16 +17,9 @@ project python/doc
<format>html:<xsl:param>chunk.section.depth=1
;
make numpy : numpy/index.rst : @sphinx-build ;
if [ os.name ] = NT
{
actions sphinx-build { chdir "$(>:D)" && make clean && make html}
}
else
{
actions sphinx-build { make -C "$(>:D)" clean html}
}
import boostbook ;
import quickbook ;
import docutils ;
boostbook python : python.qbk
: <format>html:<name>$(here)/html
@@ -62,5 +51,5 @@ html article : article.rst
###############################################################################
alias boostdoc ;
explicit boostdoc ;
alias boostrelease : python tutorial reference numpy article ;
alias boostrelease : python tutorial reference article ;
explicit boostrelease ;

52
doc/SConscript Normal file
View File

@@ -0,0 +1,52 @@
# -*- python -*-
#
# 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)
Import('env')
env.QuickBook('python.bbk', 'python.qbk',
['building.qbk',
'configuration.qbk',
'support.qbk',
'faq.qbk',
'glossary.qbk'])
env.QuickBook('tutorial.bbk', 'tutorial.qbk')
env.QuickBook('reference.bbk', 'reference.qbk',
Glob('reference/*.qbk'))
env.BoostBook('python.dbk', 'python.bbk')
env.BoostBook('tutorial.dbk', 'tutorial.bbk')
env.BoostBook('reference.dbk', 'reference.bbk')
images = Glob('images/*.*') + Glob('images/callouts/*.*')
env.BoostHTML('html/', 'python.dbk',
resources=['boostbook.css'] + images,
args=['--stringparam', 'generate.toc', '"library nop; chapter toc; section toc;"',
'--stringparam', 'html.stylesheet', 'boostbook.css',
'--stringparam', 'boost.image.src', 'images/bpl.png',
'--stringparam', 'boost.graphics.root', 'images/',
'--stringparam', 'boost.defaults', 'none',
'--param', 'toc.max.depth', '3',
'--param', 'toc.section.depth' ,'2',
'--param', 'chunk.section.depth', '1'])
env.BoostHTML('html/tutorial/', 'tutorial.dbk',
args=['--stringparam', 'html.stylesheet', '../boostbook.css',
'--stringparam', 'boost.image.src', '../images/bpl.png',
'--stringparam', 'boost.graphics.root', '../images/'])
env.BoostHTML('html/reference/', 'reference.dbk',
args=['--stringparam', 'html.stylesheet', '../boostbook.css',
'--stringparam', 'boost.image.src', '../images/bpl.png',
'--stringparam', 'boost.graphics.root', '../images/'])
env.BoostRST('html/article.html', 'article.rst', resources=['rst.css'])
if env['NUMPY']:
env.BoostSphinx('html/numpy', 'numpy/')

View File

@@ -1,83 +0,0 @@
# -*- python -*-
#
# 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)
from faber.tools.xslt import xsltflags
from faber.tools.boost import quickbook, boostbook
from faber.artefacts import html
from glob import glob as G
from os import makedirs
from os.path import relpath, dirname, exists
from shutil import copyfile
def glob(pattern):
prefix = srcdir + '/'
p = len(prefix)+1
return [f[p:] for f in G(prefix + pattern)]
class make_html(action):
def __init__(self):
action.__init__(self, 'make_html', self.process)
def map(self, fs):
return boostbook.html.map(fs)
def process(self, target, source):
boostbook.html(target, source[0:1])
for s in source[1:]:
t = target[0]._filename + relpath(s._filename, srcdir)
d = dirname(t)
if not exists(d):
makedirs(d)
copyfile(s._filename, t)
sphinx_build = action('sphinx-build', 'sphinx-build -b html $(>) $(<)')
rst2html = action('rst2html', 'rst2html --trim-footnote-reference-space --footnote-references=superscript --stylesheet=$(>:D)/rst.css $(>) $(<)')
python_bbk = rule(quickbook.process, 'python.bbk', 'python.qbk',
dependencies=['release_notes.qbk',
'building.qbk',
'configuration.qbk',
'suport.qbk',
'faq.qbk',
'glossary.qbk'])
tutorial_bbk = rule(quickbook.process, 'tutorial.bbk', 'tutorial.qbk')
reference_bbk = rule(quickbook.process, 'reference.bbk', 'reference.qbk')
python_db = rule(boostbook.db, 'python.db', python_bbk)
tutorial_db = rule(boostbook.db, 'tutorial.db', tutorial_bbk)
reference_db = rule(boostbook.db, 'reference.db', reference_bbk)
python = html.dir(make_html(), 'html', [python_db, 'boostbook.css'] + glob('/images/*.*') + glob('/images/callouts/*.*'),
features=xsltflags('--stringparam generate.toc "library nop; chaper toc; section toc;"',
'--stringparam html.stylesheet boostbook.css',
'--stringparam boost.image.src images/bpl.png',
'--stringparam boost.graphics.root images/',
'--stringparam boost.defaults none',
'--param toc.max.depth 3',
'--param toc.section.depth 2',
'--param chunk.section.depth 1'))
tutorial = html.dir(boostbook.html, 'html/tutorial', tutorial_db, dependencies=[python],
features=xsltflags('--stringparam html.stylesheet ../boostbook.css',
'--stringparam boost.image.src ../images/bpl.png',
'--stringparam boost.graphics.root ../images/'))
reference = html.dir(boostbook.html, 'html/reference', reference_db, dependencies=[python],
features=xsltflags('--stringparam html.stylesheet ../boostbook.css',
'--stringparam boost.image.src ../images/bpl.png',
'--stringparam boost.graphics.root ../images/'))
numpy = rule(sphinx_build, 'html/numpy', 'numpy', attrs=always, dependencies=[python])
article = rule(rst2html, 'html/article.html', 'article.rst')
html = alias('html', [python, tutorial, reference, numpy, article])
default = html

0
doc/html/images/python_cpp_mix.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

0
doc/internals.html Normal file → Executable file
View File

0
doc/internals.rst Normal file → Executable file
View File

View File

@@ -6,7 +6,6 @@ SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
HTMLDIR = ../html/numpy
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
@@ -40,9 +39,9 @@ clean:
-rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(HTMLDIR)
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(HTMLDIR)."
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml

View File

@@ -27,12 +27,12 @@
}
.admonition-title { font-weight: bold;}
.toctree-wrapper
#table-of-contents
{
border: 1px solid #dcdcdc;
padding: 1em;
margin: 0 2em;
}
.toctree-wrapper .caption,
.toctree-wrapper .topic-title { font-weight: bold;}
#table-of-contents .caption,
#table-of-contents .topic-title { font-weight: bold;}

View File

@@ -6,7 +6,6 @@ if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set HTMLDIR=../html/numpy
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
@@ -42,10 +41,10 @@ if "%1" == "clean" (
)
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %HTMLDIR%
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %HTMLDIR%.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)

View File

@@ -2,6 +2,8 @@ Boost.Python NumPy extension Reference
======================================
.. toctree::
:caption: Table of Contents
:name: reftoc
:maxdepth: 2
dtype

View File

@@ -2,6 +2,8 @@ Boost.Python NumPy extension Tutorial
=====================================
.. toctree::
:caption: Table of Contents
:name: tuttoc
:maxdepth: 2
simple

View File

@@ -43,7 +43,6 @@ The development of these features was funded in part by grants to `Boost Consult
[section Contents]
* [link rn Release Notes]
* _tutorial_
* [link building Building and Testing]
* _reference_
@@ -59,7 +58,6 @@ The development of these features was funded in part by grants to `Boost Consult
[@article.html Building Hybrid Systems With Boost Python], by Dave Abrahams and Ralf W. Grosse-Kunstleve
[include release_notes.qbk]
[include building.qbk]
[include configuration.qbk]
[include support.qbk]

View File

@@ -20,8 +20,6 @@ C++ Module Definition
``
#include <boost/python/module.hpp>
#include <boost/python/class.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/def.hpp>
#include <boost/utility.hpp>
#include <cstring>
@@ -30,7 +28,7 @@ class Base
{
public:
virtual char const* class_name() const { return "Base"; }
virtual ~Base() {};
virtual ~Base();
};
bool is_base(Base* b)
@@ -58,7 +56,7 @@ BOOST_PYTHON_MODULE(my_module)
{
def("is_base", is_base);
class_<Base,Base_callback, boost::noncopyable>("Base")
class_<Base,Base_callback, noncopyable>("Base")
.def("class_name", &Base_callback::Base_name)
;

View File

@@ -38,7 +38,7 @@ The `indexing_suite` class is the base class for the management of C++ container
[[__iter__(self)]
[This method is called when an iterator is required for a container. This method should return a new iterator object that can iterate over all the objects in the container. For mappings, it should iterate over the keys of the container, and should also be made available as the method iterkeys().
Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see [@https://docs.python.org/3/library/stdtypes.html#iterator-types Iterator Types] in the [@https://docs.python.org/3/library/index.html Python Library Reference].]]
Iterator objects also need to implement this method; they are required to return themselves. For more information on iterator objects, see [@http://www.python.org/doc/current/lib/typeiter.html Iterator Types] in the [@http://www.python.org/doc/current/lib/lib.html Python Library Reference].]]
[[__contains__(self, item)]
[Called to implement membership test operators. Should return true if item is in self, false otherwise. For mapping objects, this should consider the keys of the mapping rather than the values or the key-item pairs.]]

153
doc/reference/numeric.qbk Normal file
View File

@@ -0,0 +1,153 @@
[section boost/python/numeric.hpp]
[section Introduction]
Exposes a [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] for the Python [@http://www.python.org/dev/doc/devel/lib/typesmapping.html array] type.
[endsect]
[section Class `array`]
Provides access to the array types of [@http://www.pfdubois.com/numpy/ Numerical Python]\ 's [@http://www.pfdubois.com/numpy/#Numeric Numeric] and [@http://stsdas.stsci.edu/numarray/index.html NumArray] modules. With the exception of the functions documented below, the semantics of the constructors and member functions defined below can be fully understood by reading the [link concepts.objectwrapper.typewrapper_concept_requirements TypeWrapper] concept definition. Since array is publicly derived from object, the public object interface applies to array instances as well.
The default behavior is to use numarray.NDArray as the associated Python type if the numarray module is installed in the default location. Otherwise it falls back to use Numeric.ArrayType. If neither extension module is installed, overloads of wrapped C++ functions with numeric::array parameters will never be matched, and other attempted uses of numeric::array will raise an appropriate Python exception. The associated Python type can be set manually using the set_module_and_type(...) static function.
``
namespace boost { namespace python { namespace numeric
{
class array : public object
{
public:
object astype();
template <class Type>
object astype(Type const& type_);
template <class Type>
array new_(Type const& type_) const;
template <class Sequence>
void resize(Sequence const& x);
void resize(long x1);
void resize(long x1, long x2);
...
void resize(long x1, long x2,...long xn);
template <class Sequence>
void setshape(Sequence const& x);
void setshape(long x1);
void setshape(long x1, long x2);
...
void setshape(long x1, long x2,...long xn);
template <class Indices, class Values>
void put(Indices const& indices, Values const& values);
template <class Sequence>
object take(Sequence const& sequence, long axis = 0);
template <class File>
void tofile(File const& f) const;
object factory();
template <class Sequence>
object factory(Sequence const&);
template <class Sequence, class Typecode>
object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
template <class Sequence, class Typecode, class Type>
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
template <class Sequence, class Typecode, class Type, class Shape>
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
template <class T1>
explicit array(T1 const& x1);
template <class T1, class T2>
explicit array(T1 const& x1, T2 const& x2);
...
template <class T1, class T2,...class Tn>
explicit array(T1 const& x1, T2 const& x2,...Tn const& xn);
static void set_module_and_type();
static void set_module_and_type(char const* package_path = 0, char const* type_name = 0);
static void get_module_name();
object argmax(long axis=-1);
object argmin(long axis=-1);
object argsort(long axis=-1);
void byteswap();
object copy() const;
object diagonal(long offset = 0, long axis1 = 0, long axis2 = 1) const;
void info() const;
bool is_c_array() const;
bool isbyteswapped() const;
void sort();
object trace(long offset = 0, long axis1 = 0, long axis2 = 1) const;
object type() const;
char typecode() const;
object getflat() const;
long getrank() const;
object getshape() const;
bool isaligned() const;
bool iscontiguous() const;
long itemsize() const;
long nelements() const;
object nonzero() const;
void ravel();
object repeat(object const& repeats, long axis=0);
void setflat(object const& flat);
void swapaxes(long axis1, long axis2);
str tostring() const;
void transpose(object const& axes = object());
object view() const;
};
}}}
``
[endsect]
[section Class `array` observer functions]
``
object factory();
template <class Sequence>
object factory(Sequence const&);
template <class Sequence, class Typecode>
object factory(Sequence const&, Typecode const&, bool copy = true, bool savespace = false);
template <class Sequence, class Typecode, class Type>
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&);
template <class Sequence, class Typecode, class Type, class Shape>
object factory(Sequence const&, Typecode const&, bool copy, bool savespace, Type const&, Shape const&);
``
These functions map to the underlying array type's array() function family. They are not called "array" because of the C++ limitation that you can't define a member function with the same name as its enclosing class.
``
template <class Type>
array new_(Type const&) const;
``
This function maps to the underlying array type's new() function. It is not called "new" because that is a keyword in C++.
[endsect]
[section Class `array` static functions]
``
static void set_module_and_type(char const* package_path, char const* type_name);
static void set_module_and_type();
``
[variablelist
[[Requires][package_path and type_name, if supplied, is an [link ntbs].]]
[[Effects][The first form sets the package path of the module that supplies the type named by type_name to package_path. The second form restores the default search behavior. The associated Python type will be searched for only the first time it is needed, and thereafter the first time it is needed after an invocation of set_module_and_type.]]
]
``static std::string get_module_name()``
[variablelist
[[Effects][Returns the name of the module containing the class that will be held by new `numeric::array` instances.]]
]
[endsect]
[section Example]
``
#include <boost/python/numeric.hpp>
#include <boost/python/tuple.hpp>
// sets the first element in a 2d numeric array
void set_first_element(numeric::array& y, double value)
{
y[make_tuple(0,0)] = value;
}
``
[endsect]
[endsect]

View File

@@ -5,6 +5,7 @@
[include dict.qbk]
[include list.qbk]
[include long.qbk]
[include numeric.qbk]
[include object.qbk]
[include str.qbk]
[include slice.qbk]

View File

@@ -86,8 +86,8 @@ The column of Python Expressions illustrates the expressions that will be suppor
[[C++ Expression][Python Method Name][C++ Implementation][Python Expression (primary, secondary)]]
[[`self == r`][`__eq__`][`x == y`][`x == y`, `y == x`]]
[[`l == self`][`__eq__`][`y == x`][`y == x`, `x == y`]]
[[`self != r`][`__ne__`][`x != y`][`x != y`, `y != x`]]
[[`l != self`][`__ne__`][`y != x`][`y != x`, `x != y`]]
[[`self != r`][`__nq__`][`x != y`][`x != y`, `y != x`]]
[[`l != self`][`__nq__`][`y != x`][`y != x`, `x != y`]]
[[`self < r`][`__lt__`][`x < y`][`x < y`, `y > x`]]
[[`l < self`][`__gt__`][`y < x`][`y > x`, `x < y`]]
[[`self > r`][`__gt__`][`x > y`][`x > y`, `y < x`]]

View File

@@ -4,7 +4,7 @@ Pickle is a Python module for object serialization, also known as persistence, m
It is often necessary to save and restore the contents of an object to a file. One approach to this problem is to write a pair of functions that read and write data from a file in a special format. A powerful alternative approach is to use Python's pickle module. Exploiting Python's ability for introspection, the pickle module recursively converts nearly arbitrary Python objects into a stream of bytes that can be written to a file.
The Boost Python Library supports the pickle module through the interface as described in detail in the [@https://docs.python.org/2/library/pickle.html Python Library Reference for pickle]. This interface involves the special methods `__getinitargs__`, `__getstate__` and `__setstate__` as described in the following. Note that `Boost.Python` is also fully compatible with Python's cPickle module.
The Boost Python Library supports the pickle module through the interface as described in detail in the [@http://www.python.org/doc/current/lib/module-pickle.html Python Library Reference for pickle]. This interface involves the special methods `__getinitargs__`, `__getstate__` and `__setstate__` as described in the following. Note that `Boost.Python` is also fully compatible with Python's cPickle module.
[endsect]
[section The Pickle Interface]
At the user level, the Boost.Python pickle interface involves three special methods:

View File

@@ -105,6 +105,14 @@ list odd_elements(list l)
return l[slice(_,_,2)];
}
// Perform a multidimensional extended slice of a Numeric.array
numeric::array even_columns(numeric::array arr)
{
// select every other column, starting with the second, of a 2-D array.
// Equivalent to "return arr[:, 1::2]" in Python.
return arr[make_tuple( slice(), slice(1,_,2))];
}
// Perform a summation over a slice of a std::vector.
double partial_sum(std::vector<double> const& Foo, const slice index)
{

View File

@@ -1,11 +0,0 @@
[chapter Release Notes
[quickbook 1.7]
[id rn]
]
[section Version 1.67]
* The Boost.Python library names now contain the Python version suffix.
A variant compiled with Python 2.7 will thus produce library names
`boost_python27` and `boost_numpy27`, etc., making it possible to host
variants for multiple Python versions next to each other.

View File

@@ -92,7 +92,7 @@ who had to use a different tool.
We will skip over the details. Our objective will be to simply create
the hello world module and run it in Python. For a complete reference to
building Boost.Python, check out: [@../building.html
building Boost.Python, check out: [@../../../building.html
building.html]. After this brief ['bjam] tutorial, we should have built
the DLLs and run a python program using the extension.
@@ -121,7 +121,7 @@ __jam__
file. Simply copy the file and tweak [^use-project boost] to where your
boost root directory is and you're OK.
The comments contained in the Jamroot file above should be sufficient
The comments contained in the Jamrules file above should be sufficient
to get you going.
[h2 Running bjam]
@@ -1417,8 +1417,6 @@ eval evaluates the given expression and returns the resulting value.
exec executes the given code (typically a set of statements) returning the result,
and exec_file executes the code contained in the given file.
There are also overloads taking `char const*` instead of str as the first argument.
The [^globals] and [^locals] parameters are Python dictionaries
containing the globals and locals of the context in which to run the code.
For most intents and purposes you can use the namespace dictionary of the
@@ -1871,6 +1869,36 @@ This technique has several advantages:
* Minimize the need to recompile
* Rapid prototyping (you can move the code to C++ if required without changing the interface)
You can even add a little syntactic sugar with the use of metaclasses. Let's
create a special metaclass that "injects" methods in other classes.
# The one Boost.Python uses for all wrapped classes.
# You can use here any class exported by Boost instead of "point"
BoostPythonMetaclass = point.__class__
class injector(object):
class __metaclass__(BoostPythonMetaclass):
def __init__(self, name, bases, dict):
for b in bases:
if type(b) not in (self, type):
for k,v in dict.items():
setattr(b,k,v)
return type.__init__(self, name, bases, dict)
# inject some methods in the point foo
class more_point(injector, point):
def __repr__(self):
return 'Point(x=%s, y=%s)' % (self.x, self.y)
def foo(self):
print 'foo!'
Now let's see how it got:
>>> print point()
Point(x=10, y=10)
>>> point().foo()
foo!
Another useful idea is to replace constructors with factory functions:
_point = point

View File

@@ -1,35 +1,43 @@
# Copyright Stefan Seefeld 2016.
# 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)
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
if ! [ python.configured ]
{
ECHO "warning: no Python configured in user-config.jam" ;
ECHO "warning: will use default configuration" ;
using python ;
}
# Adjust the following if Boost.Python isn't installed in a default location
lib boost_python ;
# Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost
: ../../.. ;
# Set up the project-wide requirements that everything uses the
# boost_python library from the project whose global ID is
# /boost/python.
project
: requirements
# <include>/path/to/boost/python
<library>boost_python
;
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
rule run-test ( test-name : sources + )
# Declare the three extension modules. You can specify multiple
# source files after the colon separated by spaces.
python-extension getting_started1 : getting_started1.cpp ;
python-extension getting_started2 : getting_started2.cpp ;
python-extension std_pair_ext : std_pair.cpp ;
# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
local rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
build-project quickstart ;
build-project tutorial ;
if [ python.numpy ]
{
build-project numpy ;
}
# Declare test targets
run-test test1 : getting_started1 test_getting_started1.py ;
run-test test2 : getting_started2 test_getting_started2.py ;
run-test test3 : std_pair_ext test_std_pair.py ;
# A target that runs all the tests
alias test : test1 test2 test3 ;
# Only run tests when explicitly requested
explicit test test1 test2 test3 ;

16
example/README Normal file
View File

@@ -0,0 +1,16 @@
.. Copyright David Abrahams 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)
To get started with the Boost Python Library, use the examples
getting_started1.cpp and getting_started2.cpp. Invoking
bjam --toolset=your-toolset test
in this directory will build and run the examples. See
http://www.boost.org/more/getting_started.html for details about the
--toolset= option.
If you move this example from its place in the Boost development tree
you'll need to edit the two lines indicated in Jamroot and
boost-build.jam.

View File

@@ -1,11 +0,0 @@
![logo](https://raw.githubusercontent.com/boostorg/python/develop/doc/images/bpl.png)
# Examples
This directory contains various examples using Boost.Python.
You may compile these using the `bjam` 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.
See http://boostorg.github.io/python/doc/html/building/no_install_quickstart.html
for details.

7
example/boost-build.jam Executable file
View File

@@ -0,0 +1,7 @@
# Copyright David Abrahams 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)
# Edit this path to point at the tools/build/src subdirectory of your
# Boost installation. Absolute paths work, too.
boost-build ../../../tools/build/src ;

View File

@@ -0,0 +1,25 @@
// Copyright Ralf W. Grosse-Kunstleve 2002-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)
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <string>
namespace { // Avoid cluttering the global namespace.
// A couple of simple C++ functions that we want to expose to Python.
std::string greet() { return "hello, world"; }
int square(int number) { return number * number; }
}
namespace python = boost::python;
// Python requires an exported function called init<module-name> in every
// extension module. This is where we build the module contents.
BOOST_PYTHON_MODULE(getting_started1)
{
// Add regular functions to the module.
python::def("greet", greet);
python::def("square", square);
}

View File

@@ -0,0 +1,41 @@
// Copyright Ralf W. Grosse-Kunstleve 2002-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)
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <iostream>
#include <string>
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class hello
{
public:
hello(const std::string& country) { this->country = country; }
std::string greet() const { return "Hello from " + country; }
private:
std::string country;
};
// A function taking a hello object as an argument.
std::string invite(const hello& w) {
return w.greet() + "! Please come soon!";
}
}
BOOST_PYTHON_MODULE(getting_started2)
{
using namespace boost::python;
class_<hello>("hello", init<std::string>())
// Add a regular member function.
.def("greet", &hello::greet)
// Add invite() as a member of hello!
.def("invite", invite)
;
// Also add invite() as a regular function to the module.
def("invite", invite);
}

View File

@@ -1,29 +0,0 @@
# Copyright Stefan Seefeld 2016.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import python ;
# Adjust the following if Boost.Python isn't installed in a default location
lib boost_numpy
:
: <search>/usr/local/Boost/lib
<include>/usr/local/Boost/include
;
project numpy
: requirements
<include>/usr/local/Boost/include
<library>boost_numpy
<location>.
;
exe simple : simple.cpp boost_numpy /python//python ;
exe dtype : dtype.cpp boost_numpy /python//python ;
exe ndarray : ndarray.cpp /python//python ;
exe fromdata : fromdata.cpp /python//python ;
exe ufunc : ufunc.cpp /python//python ;
exe wrap : wrap.cpp /python//python ;
python-extension gaussian : gaussian.cpp ;

View File

@@ -12,11 +12,11 @@
*
*/
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
int main(int argc, char **argv)
{

View File

@@ -8,11 +8,11 @@
* manipulate data in either Python or C++ and have the changes reflected in both.
*/
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
int main(int argc, char **argv)

View File

@@ -3,7 +3,7 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <cmath>
#include <memory>
@@ -14,7 +14,7 @@ const double M_PI = boost::math::constants::pi<double>();
#endif
namespace bp = boost::python;
namespace bn = boost::python::numpy;
namespace bn = boost::numpy;
/**
* A 2x2 matrix class, purely for demonstration purposes.

View File

@@ -11,11 +11,11 @@
* non-unit strides.
*/
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
#if _MSC_VER
using boost::uint8_t;

View File

@@ -3,11 +3,11 @@
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
int main(int argc, char **argv)
{

View File

@@ -11,11 +11,11 @@
* None of the methods like np::add, np::multiply etc are supported as yet
*/
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
// Create the structs necessary to implement the ufuncs

View File

@@ -23,12 +23,12 @@
* Python. Again, see the Gaussian demo for an example.
*/
#include <boost/python/numpy.hpp>
#include <boost/numpy.hpp>
#include <boost/scoped_array.hpp>
#include <iostream>
namespace p = boost::python;
namespace np = boost::python::numpy;
namespace np = boost::numpy;
// This is roughly the most efficient way to write a C/C++ function that operates
// on a 2-d NumPy array - operate directly on the array by incrementing a pointer

BIN
example/project.zip Normal file

Binary file not shown.

View File

@@ -1,22 +1,32 @@
# Copyright Stefan Seefeld 2016.
# 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)
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
import testing ;
# Specify the path to the Boost project. If you move this project,
# adjust the path to refer to the Boost root directory.
use-project boost
: ../../../.. ;
project quickstart
: requirements
<location>.
# Set up the project-wide requirements that everything uses the
# boost_python library defined in the project whose global ID is
# /boost/python.
project boost-python-quickstart
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
# Make the definition of the python-extension rule available
import python ;
# Declare a Python extension called hello.
python-extension extending : extending.cpp ;
# Declare an executable called embedding that embeds Python
exe embedding : embedding.cpp /python//python ;
import testing ;
# Declare a test of the extension module
testing.make-test run-pyd : extending test_extending.py : : test_ext ;

View File

@@ -0,0 +1,7 @@
# Copyright David Abrahams 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)
# Edit this path to point at the tools/build/src subdirectory of your
# Boost installation. Absolute paths work, too.
boost-build ../../../../tools/build/src ;

View File

@@ -1,7 +1,6 @@
#! /usr/bin/env python
# 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)
print('Hello World !')
print 'Hello World !'
number = 42

View File

@@ -1,4 +1,3 @@
#! /usr/bin/env python
# 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)

49
example/std_pair.cpp Normal file
View File

@@ -0,0 +1,49 @@
// Copyright Ralf W. Grosse-Kunstleve 2002-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)
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/tuple.hpp>
#include <boost/python/to_python_converter.hpp>
namespace { // Avoid cluttering the global namespace.
// Converts a std::pair instance to a Python tuple.
template <typename T1, typename T2>
struct std_pair_to_tuple
{
static PyObject* convert(std::pair<T1, T2> const& p)
{
return boost::python::incref(
boost::python::make_tuple(p.first, p.second).ptr());
}
static PyTypeObject const *get_pytype () {return &PyTuple_Type; }
};
// Helper for convenience.
template <typename T1, typename T2>
struct std_pair_to_python_converter
{
std_pair_to_python_converter()
{
boost::python::to_python_converter<
std::pair<T1, T2>,
std_pair_to_tuple<T1, T2>,
true //std_pair_to_tuple has get_pytype
>();
}
};
// Example function returning a std::pair.
std::pair<int, int>
foo() { return std::pair<int, int>(3, 5); }
} // namespace anonymous
BOOST_PYTHON_MODULE(std_pair_ext)
{
using namespace boost::python;
std_pair_to_python_converter<int, int>();
def("foo", foo);
}

View File

@@ -0,0 +1,21 @@
# 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)
r'''>>> import getting_started1
>>> print getting_started1.greet()
hello, world
>>> number = 11
>>> print number, '*', number, '=', getting_started1.square(number)
11 * 11 = 121
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started1
return doctest.testmod(test_getting_started1)
if __name__ == '__main__':
import sys
sys.exit(run()[0])

View File

@@ -0,0 +1,34 @@
# 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)
r'''>>> from getting_started2 import *
>>> hi = hello('California')
>>> hi.greet()
'Hello from California'
>>> invite(hi)
'Hello from California! Please come soon!'
>>> hi.invite()
'Hello from California! Please come soon!'
>>> class wordy(hello):
... def greet(self):
... return hello.greet(self) + ', where the weather is fine'
...
>>> hi2 = wordy('Florida')
>>> hi2.greet()
'Hello from Florida, where the weather is fine'
>>> invite(hi2)
'Hello from Florida! Please come soon!'
'''
def run(args = None):
if args is not None:
import sys
sys.argv = args
import doctest, test_getting_started2
return doctest.testmod(test_getting_started2)
if __name__ == '__main__':
import sys
sys.exit(run()[0])

6
example/test_std_pair.py Normal file
View File

@@ -0,0 +1,6 @@
# 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)
import std_pair_ext
assert std_pair_ext.foo() == (3, 5)
print "OK"

View File

@@ -1,19 +0,0 @@
# Copyright Stefan Seefeld 2016.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
import python ;
project tutorial
: requirements
<location>.
;
python-extension hello_ext : hello.cpp ;
run-test hello : hello_ext hello.py ;
alias test : hello ;
explicit test ;

51
example/tutorial/Jamroot Normal file
View File

@@ -0,0 +1,51 @@
# Copyright David Abrahams 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import python ;
if ! [ python.configured ]
{
ECHO "notice: no Python configured in user-config.jam" ;
ECHO "notice: will use default configuration" ;
using python ;
}
# Specify the path to the Boost project. If you move this project,
# adjust this path to refer to the Boost root directory.
use-project boost
: ../../../.. ;
# Set up the project-wide requirements that everything uses the
# boost_python library from the project whose global ID is
# /boost/python.
project
: requirements <library>/boost/python//boost_python
<implicit-dependency>/boost//headers
: usage-requirements <implicit-dependency>/boost//headers
;
# Declare the three extension modules. You can specify multiple
# source files after the colon separated by spaces.
python-extension hello_ext : hello.cpp ;
# Put the extension and Boost.Python DLL in the current directory, so
# that running script by hand works.
install convenient_copy
: hello_ext
: <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION
<location>.
;
# A little "rule" (function) to clean up the syntax of declaring tests
# of these extension modules.
local rule run-test ( test-name : sources + )
{
import testing ;
testing.make-test run-pyd : $(sources) : : $(test-name) ;
}
# Declare test targets
run-test hello : hello_ext hello.py ;

View File

@@ -1,8 +1,7 @@
#! /usr/bin/env python
# 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)
# Hello World Example from the tutorial
import hello_ext
print(hello_ext.greet())
print hello_ext.greet()

View File

@@ -1,82 +0,0 @@
# -*- python -*-
#
# 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)
from faber.feature import set
from faber.types import cxx
from faber.tools.compiler import cxxflags, define, include
from faber.tools.python import python
from faber.config import report, cxx_checks
from faber.config.try_run import try_run
features += include('include')
features += define('BOOST_ALL_NO_LIB') # disable auto-linking
boost_include = options.get_with('boost-include')
if boost_include:
features += include(boost_include)
python = python.instance()
py_suffix = '{}{}'.format(*python.version.split('.')[:2])
features |= set(python.include, python.linkpath, python.libs)
class has_numpy(try_run):
src = r"""
// If defined, enforces linking against PythonXXd.lib, which
// is usually not included in Python environments.
#undef _DEBUG
#include "Python.h"
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include "numpy/arrayobject.h"
#if PY_VERSION_HEX >= 0x03000000
void *initialize() { import_array();}
#else
void initialize() { import_array();}
#endif
int main()
{
int result = 0;
Py_Initialize();
initialize();
if (PyErr_Occurred())
{
result = 1;
}
else
{
npy_intp dims = 2;
PyObject * a = PyArray_SimpleNew(1, &dims, NPY_INT);
if (!a) result = 1;
Py_DECREF(a);
}
Py_Finalize();
return result;
}
"""
def __init__(self, features=()):
inc = ''
try:
inc = python.check_python('import numpy; print(numpy.get_include())')
features |= include(inc)
except Exception:
# ignore errors, the check will fail during compilation...
pass
try_run.__init__(self, 'has_numpy', has_numpy.src, cxx, features,
if_=(include(inc), define('HAS_NUMPY')))
checks = [cxx_checks.has_cxx11(features, define('HAS_CXX11')),
has_numpy(features)]
config = report('config', checks)
src = module('src', features=features|config.use)
test = module('test', features=features|config.use)
doc = module('doc', features=features|config.use)
default = src.default

View File

@@ -42,6 +42,7 @@
# include <boost/python/make_function.hpp>
# include <boost/python/manage_new_object.hpp>
# include <boost/python/module.hpp>
# include <boost/python/numeric.hpp>
# include <boost/python/object.hpp>
# include <boost/python/object_protocol.hpp>
# include <boost/python/object_protocol_core.hpp>

6
include/boost/python/arg_from_python.hpp Normal file → Executable file
View File

@@ -9,7 +9,7 @@
# include <boost/python/converter/arg_from_python.hpp>
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/remove_cv.hpp>
#endif
namespace boost { namespace python {
@@ -19,7 +19,7 @@ struct arg_from_python
: converter::select_arg_from_python<
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
typename detail::remove_cv<T>::type
typename boost::remove_cv<T>::type
# else
T
# endif
@@ -28,7 +28,7 @@ struct arg_from_python
typedef typename converter::select_arg_from_python<
# if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \
|| BOOST_WORKAROUND(BOOST_INTEL_WIN, BOOST_TESTED_AT(800))
typename detail::remove_cv<T>::type
typename boost::remove_cv<T>::type
# else
T
# endif

View File

@@ -11,7 +11,10 @@
# include <boost/config.hpp>
# include <boost/python/detail/preprocessor.hpp>
# include <boost/python/detail/type_list.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/is_reference.hpp>
# include <boost/type_traits/remove_reference.hpp>
# include <boost/type_traits/remove_cv.hpp>
# include <boost/preprocessor/enum_params.hpp>
# include <boost/preprocessor/repeat.hpp>
@@ -113,9 +116,9 @@ namespace detail
template <class T>
struct is_reference_to_keywords
{
BOOST_STATIC_CONSTANT(bool, is_ref = detail::is_reference<T>::value);
typedef typename detail::remove_reference<T>::type deref;
typedef typename detail::remove_cv<deref>::type key_t;
BOOST_STATIC_CONSTANT(bool, is_ref = is_reference<T>::value);
typedef typename remove_reference<T>::type deref;
typedef typename remove_cv<deref>::type key_t;
BOOST_STATIC_CONSTANT(bool, is_key = is_keywords<key_t>::value);
BOOST_STATIC_CONSTANT(bool, value = (is_ref & is_key));

0
include/boost/python/base_type_traits.hpp Normal file → Executable file
View File

View File

@@ -6,8 +6,8 @@
# define BASES_DWA2002321_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/python/detail/type_list.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/mpl/bool.hpp>
# include <boost/preprocessor/enum_params_with_a_default.hpp>

0
include/boost/python/borrowed.hpp Normal file → Executable file
View File

View File

@@ -60,7 +60,7 @@ call(PyObject* callable
)
{
PyObject* const result =
PyObject_CallFunction(
PyEval_CallFunction(
callable
, const_cast<char*>("(" BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FIXED, "O") ")")
BOOST_PP_REPEAT_1ST(N, BOOST_PYTHON_FAST_ARG_TO_PYTHON_GET, nil)
@@ -69,7 +69,7 @@ call(PyObject* callable
// This conversion *must not* be done in the same expression as
// the call, because, in the special case where the result is a
// reference a Python object which was created by converting a C++
// argument for passing to PyObject_CallFunction, its reference
// argument for passing to PyEval_CallFunction, its reference
// count will be 2 until the end of the full expression containing
// the conversion, and that interferes with dangling
// pointer/reference detection.

View File

@@ -69,7 +69,7 @@ call_method(PyObject* self, char const* name
// This conversion *must not* be done in the same expression as
// the call, because, in the special case where the result is a
// reference a Python object which was created by converting a C++
// argument for passing to PyObject_CallFunction, its reference
// argument for passing to PyEval_CallFunction, its reference
// count will be 2 until the end of the full expression containing
// the conversion, and that interferes with dangling
// pointer/reference detection.

9
include/boost/python/cast.hpp Normal file → Executable file
View File

@@ -6,8 +6,9 @@
# define CAST_DWA200269_HPP
# include <boost/python/detail/prefix.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/same_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type.hpp>
# include <boost/python/base_type_traits.hpp>
# include <boost/python/detail/convertible.hpp>
@@ -75,9 +76,9 @@ namespace detail
template <class Source, class Target>
inline Target* upcast_impl(Source* x, Target*)
{
typedef typename detail::add_cv<Source>::type src_t;
typedef typename detail::add_cv<Target>::type target_t;
bool const same = detail::is_same<src_t,target_t>::value;
typedef typename add_cv<Source>::type src_t;
typedef typename add_cv<Target>::type target_t;
bool const same = is_same<src_t,target_t>::value;
return detail::upcaster<same>::execute(x, (Target*)0);
}

View File

@@ -28,10 +28,13 @@
# include <boost/python/detail/operator_id.hpp>
# include <boost/python/detail/def_helper.hpp>
# include <boost/python/detail/force_instantiate.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/python/detail/unwrap_type_id.hpp>
# include <boost/python/detail/unwrap_wrapper.hpp>
# include <boost/type_traits/is_same.hpp>
# include <boost/type_traits/is_member_function_pointer.hpp>
# include <boost/type_traits/is_polymorphic.hpp>
# include <boost/mpl/size.hpp>
# include <boost/mpl/for_each.hpp>
# include <boost/mpl/bool.hpp>
@@ -50,6 +53,7 @@
# ifdef BOOST_PYTHON_NO_MEMBER_POINTER_ORDERING
# include <boost/mpl/and.hpp>
# include <boost/type_traits/is_member_pointer.hpp>
# endif
namespace boost { namespace python {
@@ -80,8 +84,8 @@ namespace detail
template <class T>
struct is_data_member_pointer
: mpl::and_<
detail::is_member_pointer<T>
, mpl::not_<detail::is_member_function_pointer<T> >
is_member_pointer<T>
, mpl::not_<is_member_function_pointer<T> >
>
{};
@@ -134,11 +138,11 @@ namespace detail
must_be_derived_class_member(Default const&)
{
// https://svn.boost.org/trac/boost/ticket/5803
//typedef typename assertion<mpl::not_<detail::is_same<Default,Fn> > >::failed test0;
//typedef typename assertion<mpl::not_<is_same<Default,Fn> > >::failed test0;
# if !BOOST_WORKAROUND(__MWERKS__, <= 0x2407)
typedef typename assertion<detail::is_polymorphic<T> >::failed test1 BOOST_ATTRIBUTE_UNUSED;
typedef typename assertion<is_polymorphic<T> >::failed test1 BOOST_ATTRIBUTE_UNUSED;
# endif
typedef typename assertion<detail::is_member_function_pointer<Fn> >::failed test2 BOOST_ATTRIBUTE_UNUSED;
typedef typename assertion<is_member_function_pointer<Fn> >::failed test2 BOOST_ATTRIBUTE_UNUSED;
not_a_derived_class_member<Default>(Fn());
}
};

View File

@@ -8,7 +8,8 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/converter/from_python.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/python/converter/rvalue_from_python_data.hpp>
# include <boost/mpl/eval_if.hpp>
# include <boost/mpl/if.hpp>
@@ -105,7 +106,7 @@ struct reference_arg_from_python : arg_lvalue_from_python_base
template <class T>
struct arg_rvalue_from_python
{
typedef typename boost::python::detail::add_lvalue_reference<
typedef typename boost::add_reference<
T
// We can't add_const here, or it would be impossible to pass
// auto_ptr<U> args from Python to C++

12
include/boost/python/converter/arg_to_python.hpp Normal file → Executable file
View File

@@ -24,7 +24,11 @@
# include <boost/python/detail/convertible.hpp>
# include <boost/python/detail/string_literal.hpp>
# include <boost/python/detail/value_is_shared_ptr.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
# include <boost/type_traits/function_traits.hpp>
# include <boost/mpl/or.hpp>
@@ -112,9 +116,9 @@ namespace detail
, typename mpl::if_<
mpl::or_<
boost::python::detail::is_function<T>
is_function<T>
, indirect_traits::is_pointer_to_function<T>
, boost::python::detail::is_member_function_pointer<T>
, is_member_function_pointer<T>
>
, function_arg_to_python<T>
@@ -123,7 +127,7 @@ namespace detail
, object_manager_arg_to_python<T>
, typename mpl::if_<
boost::python::detail::is_pointer<T>
is_pointer<T>
, pointer_deep_arg_to_python<T>
, typename mpl::if_<

View File

View File

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

View File

@@ -8,7 +8,7 @@
# include <boost/python/handle.hpp>
# include <boost/python/cast.hpp>
# include <boost/python/converter/pyobject_traits.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/object_traits.hpp>
# include <boost/mpl/if.hpp>
# include <boost/python/detail/indirect_traits.hpp>
# include <boost/mpl/bool.hpp>

View File

@@ -6,7 +6,7 @@
# define POINTER_TYPE_ID_DWA2002222_HPP
# include <boost/python/type_id.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/composite_traits.hpp>
namespace boost { namespace python { namespace converter {
@@ -59,7 +59,7 @@ template <class T>
type_info pointer_type_id(T(*)() = 0)
{
return detail::pointer_typeid_select<
boost::python::detail::is_lvalue_reference<T>::value
is_reference<T>::value
>::execute((T(*)())0);
}

View File

@@ -9,11 +9,8 @@
namespace boost { namespace python { namespace converter {
BOOST_PYTHON_DECL inline
PyObject* checked_downcast_impl(PyObject *obj, PyTypeObject *type)
{
return (PyType_IsSubtype(Py_TYPE(obj), type) ? obj : NULL);
}
BOOST_PYTHON_DECL PyObject* checked_downcast_impl(PyObject*, PyTypeObject*);
// Used as a base class for specializations which need to provide
// Python type checking capability.
template <class Object, PyTypeObject* pytype>

9
include/boost/python/converter/pytype_function.hpp Normal file → Executable file
View File

@@ -8,7 +8,6 @@
# include <boost/python/detail/prefix.hpp>
# include <boost/python/converter/registered.hpp>
# include <boost/python/detail/unwind_type.hpp>
# include <boost/python/detail/type_traits.hpp>
namespace boost { namespace python {
@@ -54,7 +53,7 @@ inline python::type_info unwind_type_id_(boost::type<void>* = 0, mpl::true_* =0)
template <class T>
inline python::type_info unwind_type_id(boost::type<T>* p= 0)
{
return unwind_type_id_(p, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 );
return unwind_type_id_(p, (mpl::bool_<boost::is_void<T>::value >*)0 );
}
}
@@ -65,7 +64,7 @@ struct expected_pytype_for_arg
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 )
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
);
return r ? r->expected_from_python_type(): 0;
}
@@ -78,7 +77,7 @@ struct registered_pytype
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 )
detail::unwind_type_id_((boost::type<T>*) 0, (mpl::bool_<boost::is_void<T>::value >*)0 )
);
return r ? r->m_class_object: 0;
}
@@ -112,7 +111,7 @@ struct to_python_target_type
static PyTypeObject const *get_pytype()
{
const converter::registration *r=converter::registry::query(
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::python::detail::is_void<T>::value >*)0 )
detail::unwind_type_id_((boost::type<T>*)0, (mpl::bool_<boost::is_void<T>::value >*)0 )
);
return r ? r->to_python_target_type(): 0;
}

View File

@@ -10,7 +10,9 @@
#include <boost/python/type_id.hpp>
#include <boost/python/converter/registry.hpp>
#include <boost/python/converter/registrations.hpp>
#include <boost/python/detail/type_traits.hpp>
#include <boost/type_traits/transform_traits.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/type_traits/is_void.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/type.hpp>
#include <memory>
@@ -42,8 +44,8 @@ namespace detail
template <class T>
struct registered
: detail::registered_base<
typename boost::python::detail::add_lvalue_reference<
typename boost::python::detail::add_cv<T>::type
typename add_reference<
typename add_cv<T>::type
>::type
>
{
@@ -76,7 +78,7 @@ namespace detail
registry::lookup_shared_ptr(type_id<shared_ptr<T> >());
}
#if !defined(BOOST_NO_CXX11_SMART_PTR)
#if __cplusplus >= 201103L
template <class T>
inline void
register_shared_ptr0(std::shared_ptr<T>*)

View File

@@ -7,7 +7,8 @@
# include <boost/python/converter/registered.hpp>
# include <boost/python/converter/pointer_type_id.hpp>
# include <boost/python/converter/registry.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/transform_traits.hpp>
# include <boost/type_traits/cv_traits.hpp>
namespace boost { namespace python { namespace converter {
@@ -16,9 +17,9 @@ struct registration;
template <class T>
struct registered_pointee
: registered<
typename boost::python::detail::remove_pointer<
typename boost::python::detail::remove_cv<
typename boost::python::detail::remove_reference<T>::type
typename remove_pointer<
typename remove_cv<
typename remove_reference<T>::type
>::type
>::type
>

2
include/boost/python/converter/return_from_python.hpp Normal file → Executable file
View File

@@ -14,7 +14,7 @@
# include <boost/python/detail/void_return.hpp>
# include <boost/python/errors.hpp>
# include <boost/python/handle.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/type_traits/has_trivial_copy.hpp>
# include <boost/mpl/and.hpp>
# include <boost/mpl/bool.hpp>

View File

@@ -8,9 +8,9 @@
# include <boost/python/converter/constructor_function.hpp>
# include <boost/python/detail/referent_storage.hpp>
# include <boost/python/detail/destroy.hpp>
# include <boost/python/detail/type_traits.hpp>
# include <boost/align/align.hpp>
# include <boost/static_assert.hpp>
# include <boost/type_traits/add_reference.hpp>
# include <boost/type_traits/add_cv.hpp>
# include <cstddef>
// Data management for potential rvalue conversions from Python to C++
@@ -78,7 +78,7 @@ struct rvalue_from_python_storage
// Storage for the result, in case an rvalue must be constructed
typename python::detail::referent_storage<
typename boost::python::detail::add_lvalue_reference<T>::type
typename add_reference<T>::type
>::type storage;
};
@@ -110,8 +110,7 @@ struct rvalue_from_python_data : rvalue_from_python_storage<T>
// Destroys any object constructed in the storage.
~rvalue_from_python_data();
private:
typedef typename boost::python::detail::add_lvalue_reference<
typename boost::python::detail::add_cv<T>::type>::type ref_type;
typedef typename add_reference<typename add_cv<T>::type>::type ref_type;
};
//
@@ -133,13 +132,7 @@ template <class T>
inline rvalue_from_python_data<T>::~rvalue_from_python_data()
{
if (this->stage1.convertible == this->storage.bytes)
{
size_t allocated = sizeof(this->storage);
void *ptr = this->storage.bytes;
void *aligned_storage =
::boost::alignment::align(boost::python::detail::alignment_of<T>::value, 0, ptr, allocated);
python::detail::destroy_referent<ref_type>(aligned_storage);
}
python::detail::destroy_referent<ref_type>(this->storage.bytes);
}
}}} // namespace boost::python::converter

View File

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

Some files were not shown because too many files have changed in this diff Show More