mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +00:00
Merge branch 'master' into stable
This commit is contained in:
commit
9371614764
62
.github/workflows/ci.yml
vendored
62
.github/workflows/ci.yml
vendored
@ -23,35 +23,39 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
runs-on: [ubuntu-latest, windows-latest, macos-latest]
|
runs-on: [ubuntu-latest, windows-2022, macos-latest]
|
||||||
python:
|
python:
|
||||||
- '2.7'
|
- '2.7'
|
||||||
- '3.5'
|
- '3.5'
|
||||||
- '3.6'
|
- '3.6'
|
||||||
- '3.9'
|
- '3.9'
|
||||||
- '3.10'
|
- '3.10'
|
||||||
# - '3.11-dev'
|
- 'pypy-3.7-v7.3.7'
|
||||||
- 'pypy-3.7-v7.3.5'
|
- 'pypy-3.8-v7.3.7'
|
||||||
# - 'pypy-3.8'
|
|
||||||
|
|
||||||
# Items in here will either be added to the build matrix (if not
|
# Items in here will either be added to the build matrix (if not
|
||||||
# present), or add new keys to an existing matrix element if all the
|
# present), or add new keys to an existing matrix element if all the
|
||||||
# existing keys match.
|
# existing keys match.
|
||||||
#
|
#
|
||||||
# We support three optional keys: args (both build), args1 (first
|
# We support an optional key: args, for cmake args
|
||||||
# build), and args2 (second build).
|
|
||||||
include:
|
include:
|
||||||
# Just add a key
|
# Just add a key
|
||||||
- runs-on: ubuntu-latest
|
- runs-on: ubuntu-latest
|
||||||
python: 3.6
|
python: '3.6'
|
||||||
args: >
|
args: >
|
||||||
-DPYBIND11_FINDPYTHON=ON
|
-DPYBIND11_FINDPYTHON=ON
|
||||||
|
-DCMAKE_CXX_FLAGS="-D_=1"
|
||||||
- runs-on: windows-latest
|
- runs-on: windows-latest
|
||||||
python: 3.6
|
python: '3.6'
|
||||||
args: >
|
args: >
|
||||||
-DPYBIND11_FINDPYTHON=ON
|
-DPYBIND11_FINDPYTHON=ON
|
||||||
- runs-on: macos-latest
|
- runs-on: macos-latest
|
||||||
python: pypy-2.7
|
python: 'pypy-2.7'
|
||||||
|
# Inject a couple Windows 2019 runs
|
||||||
|
- runs-on: windows-2019
|
||||||
|
python: '3.9'
|
||||||
|
- runs-on: windows-2019
|
||||||
|
python: '2.7'
|
||||||
|
|
||||||
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"
|
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"
|
||||||
runs-on: ${{ matrix.runs-on }}
|
runs-on: ${{ matrix.runs-on }}
|
||||||
@ -65,7 +69,8 @@ jobs:
|
|||||||
python-version: ${{ matrix.python }}
|
python-version: ${{ matrix.python }}
|
||||||
|
|
||||||
- name: Setup Boost (Linux)
|
- name: Setup Boost (Linux)
|
||||||
if: runner.os == 'Linux'
|
# Can't use boost + define _
|
||||||
|
if: runner.os == 'Linux' && matrix.python != '3.6'
|
||||||
run: sudo apt-get install libboost-dev
|
run: sudo apt-get install libboost-dev
|
||||||
|
|
||||||
- name: Setup Boost (macOS)
|
- name: Setup Boost (macOS)
|
||||||
@ -122,7 +127,7 @@ jobs:
|
|||||||
run: git clean -fdx
|
run: git clean -fdx
|
||||||
|
|
||||||
# Second build - C++17 mode and in a build directory
|
# Second build - C++17 mode and in a build directory
|
||||||
- name: Configure ${{ matrix.args2 }}
|
- name: Configure C++17
|
||||||
run: >
|
run: >
|
||||||
cmake -S . -B build2
|
cmake -S . -B build2
|
||||||
-DPYBIND11_WERROR=ON
|
-DPYBIND11_WERROR=ON
|
||||||
@ -130,7 +135,6 @@ jobs:
|
|||||||
-DDOWNLOAD_EIGEN=ON
|
-DDOWNLOAD_EIGEN=ON
|
||||||
-DCMAKE_CXX_STANDARD=17
|
-DCMAKE_CXX_STANDARD=17
|
||||||
${{ matrix.args }}
|
${{ matrix.args }}
|
||||||
${{ matrix.args2 }}
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build2 -j 2
|
run: cmake --build build2 -j 2
|
||||||
@ -184,6 +188,7 @@ jobs:
|
|||||||
# setuptools
|
# setuptools
|
||||||
- name: Setuptools helpers test
|
- name: Setuptools helpers test
|
||||||
run: pytest tests/extra_setuptools
|
run: pytest tests/extra_setuptools
|
||||||
|
if: "!(matrix.python == '3.5' && matrix.runs-on == 'windows-2022')"
|
||||||
|
|
||||||
|
|
||||||
deadsnakes:
|
deadsnakes:
|
||||||
@ -244,6 +249,8 @@ jobs:
|
|||||||
python -m pip install -r tests/requirements.txt
|
python -m pip install -r tests/requirements.txt
|
||||||
|
|
||||||
- name: Configure
|
- name: Configure
|
||||||
|
env:
|
||||||
|
SETUPTOOLS_USE_DISTUTILS: stdlib
|
||||||
run: >
|
run: >
|
||||||
cmake -S . -B build
|
cmake -S . -B build
|
||||||
-DCMAKE_BUILD_TYPE=Debug
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
@ -552,37 +559,37 @@ jobs:
|
|||||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||||
cmake --build build-11 --target test_cmake_build
|
cmake --build build-11 --target test_cmake_build
|
||||||
|
|
||||||
- name: Configure C++17
|
- name: Configure C++14
|
||||||
run: |
|
run: |
|
||||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||||
cmake -S . -B build-17 \
|
cmake -S . -B build-14 \
|
||||||
-DPYBIND11_WERROR=ON \
|
-DPYBIND11_WERROR=ON \
|
||||||
-DDOWNLOAD_CATCH=ON \
|
-DDOWNLOAD_CATCH=ON \
|
||||||
-DDOWNLOAD_EIGEN=OFF \
|
-DDOWNLOAD_EIGEN=OFF \
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
-DCMAKE_CXX_STANDARD=14 \
|
||||||
-DCMAKE_CXX_COMPILER=$(which icpc) \
|
-DCMAKE_CXX_COMPILER=$(which icpc) \
|
||||||
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)")
|
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)")
|
||||||
|
|
||||||
- name: Build C++17
|
- name: Build C++14
|
||||||
run: |
|
run: |
|
||||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||||
cmake --build build-17 -j 2 -v
|
cmake --build build-14 -j 2 -v
|
||||||
|
|
||||||
- name: Python tests C++17
|
- name: Python tests C++14
|
||||||
run: |
|
run: |
|
||||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||||
sudo service apport stop
|
sudo service apport stop
|
||||||
cmake --build build-17 --target check
|
cmake --build build-14 --target check
|
||||||
|
|
||||||
- name: C++ tests C++17
|
- name: C++ tests C++14
|
||||||
run: |
|
run: |
|
||||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||||
cmake --build build-17 --target cpptest
|
cmake --build build-14 --target cpptest
|
||||||
|
|
||||||
- name: Interface test C++17
|
- name: Interface test C++14
|
||||||
run: |
|
run: |
|
||||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||||
cmake --build build-17 --target test_cmake_build
|
cmake --build build-14 --target test_cmake_build
|
||||||
|
|
||||||
|
|
||||||
# Testing on CentOS (manylinux uses a centos base, and this is an easy way
|
# Testing on CentOS (manylinux uses a centos base, and this is an easy way
|
||||||
@ -704,14 +711,11 @@ jobs:
|
|||||||
- name: Install Doxygen
|
- name: Install Doxygen
|
||||||
run: sudo apt-get install -y doxygen librsvg2-bin # Changed to rsvg-convert in 20.04
|
run: sudo apt-get install -y doxygen librsvg2-bin # Changed to rsvg-convert in 20.04
|
||||||
|
|
||||||
- name: Install docs & setup requirements
|
|
||||||
run: python3 -m pip install -r docs/requirements.txt
|
|
||||||
|
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
run: python3 -m sphinx -W -b html docs docs/.build
|
run: pipx run nox -s docs
|
||||||
|
|
||||||
- name: Make SDist
|
- name: Make SDist
|
||||||
run: python3 setup.py sdist
|
run: pipx run nox -s build -- --sdist
|
||||||
|
|
||||||
- run: git status --ignored
|
- run: git status --ignored
|
||||||
|
|
||||||
@ -723,7 +727,7 @@ jobs:
|
|||||||
- name: Compare Dists (headers only)
|
- name: Compare Dists (headers only)
|
||||||
working-directory: include
|
working-directory: include
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --user -U ../dist/*
|
python3 -m pip install --user -U ../dist/*.tar.gz
|
||||||
installed=$(python3 -c "import pybind11; print(pybind11.get_include() + '/pybind11')")
|
installed=$(python3 -c "import pybind11; print(pybind11.get_include() + '/pybind11')")
|
||||||
diff -rq $installed ./pybind11
|
diff -rq $installed ./pybind11
|
||||||
|
|
||||||
|
112
.github/workflows/upstream.yml
vendored
Normal file
112
.github/workflows/upstream.yml
vendored
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
|
||||||
|
name: Upstream
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: upstream-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
PIP_ONLY_BINARY: numpy
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
standard:
|
||||||
|
name: "🐍 3.11 dev • ubuntu-latest • x64"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: "contains(github.event.pull_request.labels.*.name, 'python dev')"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Setup Python 3.11
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: "3.11-dev"
|
||||||
|
|
||||||
|
- name: Setup Boost (Linux)
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: sudo apt-get install libboost-dev
|
||||||
|
|
||||||
|
- name: Update CMake
|
||||||
|
uses: jwlawson/actions-setup-cmake@v1.11
|
||||||
|
|
||||||
|
- name: Prepare env
|
||||||
|
run: |
|
||||||
|
python -m pip install -r tests/requirements.txt
|
||||||
|
|
||||||
|
- name: Setup annotations on Linux
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: python -m pip install pytest-github-actions-annotate-failures
|
||||||
|
|
||||||
|
# First build - C++11 mode and inplace
|
||||||
|
- name: Configure C++11
|
||||||
|
run: >
|
||||||
|
cmake -S . -B .
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=11
|
||||||
|
|
||||||
|
- name: Build C++11
|
||||||
|
run: cmake --build . -j 2
|
||||||
|
|
||||||
|
- name: Python tests C++11
|
||||||
|
run: cmake --build . --target pytest -j 2
|
||||||
|
|
||||||
|
- name: C++11 tests
|
||||||
|
run: cmake --build . --target cpptest -j 2
|
||||||
|
|
||||||
|
- name: Interface test C++11
|
||||||
|
run: cmake --build . --target test_cmake_build
|
||||||
|
|
||||||
|
- name: Clean directory
|
||||||
|
run: git clean -fdx
|
||||||
|
|
||||||
|
# Second build - C++17 mode and in a build directory
|
||||||
|
- name: Configure C++17
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build2
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=17
|
||||||
|
${{ matrix.args }}
|
||||||
|
${{ matrix.args2 }}
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build2 -j 2
|
||||||
|
|
||||||
|
- name: Python tests
|
||||||
|
run: cmake --build build2 --target pytest
|
||||||
|
|
||||||
|
- name: C++ tests
|
||||||
|
run: cmake --build build2 --target cpptest
|
||||||
|
|
||||||
|
# Third build - C++17 mode with unstable ABI
|
||||||
|
- name: Configure (unstable ABI)
|
||||||
|
run: >
|
||||||
|
cmake -S . -B build3
|
||||||
|
-DPYBIND11_WERROR=ON
|
||||||
|
-DDOWNLOAD_CATCH=ON
|
||||||
|
-DDOWNLOAD_EIGEN=ON
|
||||||
|
-DCMAKE_CXX_STANDARD=17
|
||||||
|
-DPYBIND11_INTERNALS_VERSION=10000000
|
||||||
|
"-DPYBIND11_TEST_OVERRIDE=test_call_policies.cpp;test_gil_scoped.cpp;test_thread.cpp"
|
||||||
|
${{ matrix.args }}
|
||||||
|
|
||||||
|
- name: Build (unstable ABI)
|
||||||
|
run: cmake --build build3 -j 2
|
||||||
|
|
||||||
|
- name: Python tests (unstable ABI)
|
||||||
|
run: cmake --build build3 --target pytest
|
||||||
|
|
||||||
|
- name: Interface test
|
||||||
|
run: cmake --build build2 --target test_cmake_build
|
||||||
|
|
||||||
|
# This makes sure the setup_helpers module can build packages using
|
||||||
|
# setuptools
|
||||||
|
- name: Setuptools helpers test
|
||||||
|
run: pytest tests/extra_setuptools
|
@ -15,7 +15,7 @@
|
|||||||
repos:
|
repos:
|
||||||
# Standard hooks
|
# Standard hooks
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.0.1
|
rev: v4.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- id: check-case-conflict
|
- id: check-case-conflict
|
||||||
@ -33,27 +33,27 @@ repos:
|
|||||||
exclude: ^noxfile.py$
|
exclude: ^noxfile.py$
|
||||||
|
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v2.29.0
|
rev: v2.29.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
|
|
||||||
- repo: https://github.com/PyCQA/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.9.3
|
rev: 5.10.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
|
|
||||||
# Black, the code formatter, natively supports pre-commit
|
# Black, the code formatter, natively supports pre-commit
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 21.9b0 # Keep in sync with blacken-docs
|
rev: 21.12b0 # Keep in sync with blacken-docs
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
- repo: https://github.com/asottile/blacken-docs
|
- repo: https://github.com/asottile/blacken-docs
|
||||||
rev: v1.11.0
|
rev: v1.12.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: blacken-docs
|
- id: blacken-docs
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
- black==21.9b0 # keep in sync with black hook
|
- black==21.12b0 # keep in sync with black hook
|
||||||
|
|
||||||
# Changes tabs to spaces
|
# Changes tabs to spaces
|
||||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||||
@ -61,6 +61,12 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: remove-tabs
|
- id: remove-tabs
|
||||||
|
|
||||||
|
# Autoremoves unused imports
|
||||||
|
- repo: https://github.com/hadialqattan/pycln
|
||||||
|
rev: v1.1.0
|
||||||
|
hooks:
|
||||||
|
- id: pycln
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
rev: v1.9.0
|
rev: v1.9.0
|
||||||
hooks:
|
hooks:
|
||||||
@ -98,7 +104,7 @@ repos:
|
|||||||
|
|
||||||
# Check static types with mypy
|
# Check static types with mypy
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.910-1
|
rev: v0.930
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
# Running per-file misbehaves a bit, so just run on all files, it's fast
|
# Running per-file misbehaves a bit, so just run on all files, it's fast
|
||||||
@ -122,7 +128,7 @@ repos:
|
|||||||
args: ["-L", "nd,ot,thist"]
|
args: ["-L", "nd,ot,thist"]
|
||||||
|
|
||||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||||
rev: v0.7.2.1
|
rev: v0.8.0.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: shellcheck
|
- id: shellcheck
|
||||||
|
|
||||||
|
@ -16,6 +16,11 @@ else()
|
|||||||
cmake_policy(VERSION 3.22)
|
cmake_policy(VERSION 3.22)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Avoid infinite recursion if tests include this as a subdirectory
|
||||||
|
if(DEFINED PYBIND11_MASTER_PROJECT)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
# Extract project version from source
|
# Extract project version from source
|
||||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/pybind11/detail/common.h"
|
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/pybind11/detail/common.h"
|
||||||
pybind11_version_defines REGEX "#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) ")
|
pybind11_version_defines REGEX "#define PYBIND11_VERSION_(MAJOR|MINOR|PATCH) ")
|
||||||
@ -45,13 +50,8 @@ if(NOT pybind11_FIND_QUIETLY)
|
|||||||
message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
|
message(STATUS "pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Avoid infinite recursion if tests include this as a subdirectory
|
|
||||||
if(DEFINED PYBIND11_MASTER_PROJECT)
|
|
||||||
set(PYBIND11_TEST OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check if pybind11 is being used directly or via add_subdirectory
|
# Check if pybind11 is being used directly or via add_subdirectory
|
||||||
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR AND NOT DEFINED PYBIND11_MASTER_PROJECT)
|
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
### Warn if not an out-of-source builds
|
### Warn if not an out-of-source builds
|
||||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
set(lines
|
set(lines
|
||||||
@ -80,6 +80,8 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR AND NOT DEFINED PYBIND11_MASTER_
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(pybind11_system "")
|
set(pybind11_system "")
|
||||||
|
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
else()
|
else()
|
||||||
set(PYBIND11_MASTER_PROJECT OFF)
|
set(PYBIND11_MASTER_PROJECT OFF)
|
||||||
set(pybind11_system SYSTEM)
|
set(pybind11_system SYSTEM)
|
||||||
|
@ -106,7 +106,7 @@ goodies:
|
|||||||
- Binaries are generally smaller by a factor of at least 2 compared to
|
- Binaries are generally smaller by a factor of at least 2 compared to
|
||||||
equivalent bindings generated by Boost.Python. A recent pybind11
|
equivalent bindings generated by Boost.Python. A recent pybind11
|
||||||
conversion of PyRosetta, an enormous Boost.Python binding project,
|
conversion of PyRosetta, an enormous Boost.Python binding project,
|
||||||
`reported <http://graylab.jhu.edu/RosettaCon2016/PyRosetta-4.pdf>`_
|
`reported <https://graylab.jhu.edu/Sergey/2016.RosettaCon/PyRosetta-4.pdf>`_
|
||||||
a binary size reduction of **5.4x** and compile time reduction by
|
a binary size reduction of **5.4x** and compile time reduction by
|
||||||
**5.8x**.
|
**5.8x**.
|
||||||
|
|
||||||
|
@ -18,6 +18,5 @@ ALIASES += "endrst=\endverbatim"
|
|||||||
QUIET = YES
|
QUIET = YES
|
||||||
WARNINGS = YES
|
WARNINGS = YES
|
||||||
WARN_IF_UNDOCUMENTED = NO
|
WARN_IF_UNDOCUMENTED = NO
|
||||||
PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \
|
PREDEFINED = PY_MAJOR_VERSION=3 \
|
||||||
PY_MAJOR_VERSION=3 \
|
|
||||||
PYBIND11_NOINLINE
|
PYBIND11_NOINLINE
|
||||||
|
@ -46,7 +46,7 @@ type is explicitly allowed.
|
|||||||
* function signatures and declares a local variable
|
* function signatures and declares a local variable
|
||||||
* 'value' of type inty
|
* 'value' of type inty
|
||||||
*/
|
*/
|
||||||
PYBIND11_TYPE_CASTER(inty, _("inty"));
|
PYBIND11_TYPE_CASTER(inty, const_name("inty"));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conversion part 1 (Python->C++): convert a PyObject into a inty
|
* Conversion part 1 (Python->C++): convert a PyObject into a inty
|
||||||
|
@ -52,7 +52,7 @@ can be mapped *and* if the numpy array is writeable (that is
|
|||||||
the passed variable will be transparently carried out directly on the
|
the passed variable will be transparently carried out directly on the
|
||||||
``numpy.ndarray``.
|
``numpy.ndarray``.
|
||||||
|
|
||||||
This means you can can write code such as the following and have it work as
|
This means you can write code such as the following and have it work as
|
||||||
expected:
|
expected:
|
||||||
|
|
||||||
.. code-block:: cpp
|
.. code-block:: cpp
|
||||||
|
@ -75,96 +75,96 @@ The following basic data types are supported out of the box (some may require
|
|||||||
an additional extension header to be included). To pass other data structures
|
an additional extension header to be included). To pass other data structures
|
||||||
as arguments and return values, refer to the section on binding :ref:`classes`.
|
as arguments and return values, refer to the section on binding :ref:`classes`.
|
||||||
|
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| Data type | Description | Header file |
|
| Data type | Description | Header file |
|
||||||
+====================================+===========================+===============================+
|
+====================================+===========================+===================================+
|
||||||
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``char16_t`` | UTF-16 character literal | :file:`pybind11/pybind11.h` |
|
| ``char16_t`` | UTF-16 character literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``char32_t`` | UTF-32 character literal | :file:`pybind11/pybind11.h` |
|
| ``char32_t`` | UTF-32 character literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``const char16_t *`` | UTF-16 string literal | :file:`pybind11/pybind11.h` |
|
| ``const char16_t *`` | UTF-16 string literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``const char32_t *`` | UTF-32 string literal | :file:`pybind11/pybind11.h` |
|
| ``const char32_t *`` | UTF-32 string literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::u16string`` | STL dynamic UTF-16 string | :file:`pybind11/pybind11.h` |
|
| ``std::u16string`` | STL dynamic UTF-16 string | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::u32string`` | STL dynamic UTF-32 string | :file:`pybind11/pybind11.h` |
|
| ``std::u32string`` | STL dynamic UTF-32 string | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` |
|
| ``std::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` |
|
||||||
| ``std::u16string_view``, etc. | | |
|
| ``std::u16string_view``, etc. | | |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::deque<T>`` | STL double-ended queue | :file:`pybind11/stl.h` |
|
| ``std::deque<T>`` | STL double-ended queue | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::valarray<T>`` | STL value array | :file:`pybind11/stl.h` |
|
| ``std::valarray<T>`` | STL value array | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::optional<T>`` | STL optional type (C++17) | :file:`pybind11/stl.h` |
|
| ``std::optional<T>`` | STL optional type (C++17) | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` |
|
| ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::variant<...>`` | Type-safe union (C++17) | :file:`pybind11/stl.h` |
|
| ``std::variant<...>`` | Type-safe union (C++17) | :file:`pybind11/stl.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::filesystem::path<T>`` | STL path (C++17) [#]_ | :file:`pybind11/stl.h` |
|
| ``std::filesystem::path<T>`` | STL path (C++17) [#]_ | :file:`pybind11/stl/filesystem.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``std::chrono::time_point<...>`` | STL date/time | :file:`pybind11/chrono.h` |
|
| ``std::chrono::time_point<...>`` | STL date/time | :file:`pybind11/chrono.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||||
+------------------------------------+---------------------------+-------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
|
||||||
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
||||||
``os.PathLike`` is converted to ``std::filesystem::path``, but this requires
|
``os.PathLike`` is converted to ``std::filesystem::path``, but this requires
|
||||||
|
@ -64,7 +64,7 @@ at its exception handler.
|
|||||||
+--------------------------------------+--------------------------------------+
|
+--------------------------------------+--------------------------------------+
|
||||||
|
|
||||||
Exception translation is not bidirectional. That is, *catching* the C++
|
Exception translation is not bidirectional. That is, *catching* the C++
|
||||||
exceptions defined above above will not trap exceptions that originate from
|
exceptions defined above will not trap exceptions that originate from
|
||||||
Python. For that, catch :class:`pybind11::error_already_set`. See :ref:`below
|
Python. For that, catch :class:`pybind11::error_already_set`. See :ref:`below
|
||||||
<handling_python_exceptions_cpp>` for further details.
|
<handling_python_exceptions_cpp>` for further details.
|
||||||
|
|
||||||
|
@ -306,8 +306,9 @@ The class ``py::args`` derives from ``py::tuple`` and ``py::kwargs`` derives
|
|||||||
from ``py::dict``.
|
from ``py::dict``.
|
||||||
|
|
||||||
You may also use just one or the other, and may combine these with other
|
You may also use just one or the other, and may combine these with other
|
||||||
arguments as long as the ``py::args`` and ``py::kwargs`` arguments are the last
|
arguments. Note, however, that ``py::kwargs`` must always be the last argument
|
||||||
arguments accepted by the function.
|
of the function, and ``py::args`` implies that any further arguments are
|
||||||
|
keyword-only (see :ref:`keyword_only_arguments`).
|
||||||
|
|
||||||
Please refer to the other examples for details on how to iterate over these,
|
Please refer to the other examples for details on how to iterate over these,
|
||||||
and on how to cast their entries into C++ objects. A demonstration is also
|
and on how to cast their entries into C++ objects. A demonstration is also
|
||||||
@ -366,6 +367,8 @@ like so:
|
|||||||
py::class_<MyClass>("MyClass")
|
py::class_<MyClass>("MyClass")
|
||||||
.def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));
|
.def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));
|
||||||
|
|
||||||
|
.. _keyword_only_arguments:
|
||||||
|
|
||||||
Keyword-only arguments
|
Keyword-only arguments
|
||||||
======================
|
======================
|
||||||
|
|
||||||
@ -397,6 +400,15 @@ feature does *not* require Python 3 to work.
|
|||||||
|
|
||||||
.. versionadded:: 2.6
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
|
As of pybind11 2.9, a ``py::args`` argument implies that any following arguments
|
||||||
|
are keyword-only, as if ``py::kw_only()`` had been specified in the same
|
||||||
|
relative location of the argument list as the ``py::args`` argument. The
|
||||||
|
``py::kw_only()`` may be included to be explicit about this, but is not
|
||||||
|
required. (Prior to 2.9 ``py::args`` may only occur at the end of the argument
|
||||||
|
list, or immediately before a ``py::kwargs`` argument at the end).
|
||||||
|
|
||||||
|
.. versionadded:: 2.9
|
||||||
|
|
||||||
Positional-only arguments
|
Positional-only arguments
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ a file named :file:`example.cpp` with the following contents:
|
|||||||
PYBIND11_MODULE(example, m) {
|
PYBIND11_MODULE(example, m) {
|
||||||
m.doc() = "pybind11 example plugin"; // optional module docstring
|
m.doc() = "pybind11 example plugin"; // optional module docstring
|
||||||
|
|
||||||
m.def("add", &add, "A function which adds two numbers");
|
m.def("add", &add, "A function that adds two numbers");
|
||||||
}
|
}
|
||||||
|
|
||||||
.. [#f1] In practice, implementation and binding code will generally be located
|
.. [#f1] In practice, implementation and binding code will generally be located
|
||||||
|
@ -7,8 +7,100 @@ Starting with version 1.8.0, pybind11 releases use a `semantic versioning
|
|||||||
<http://semver.org>`_ policy.
|
<http://semver.org>`_ policy.
|
||||||
|
|
||||||
|
|
||||||
IN DEVELOPMENT
|
Version 2.9.0 (Dec 28, 2021)
|
||||||
--------------
|
----------------------------
|
||||||
|
|
||||||
|
This is the last version to support Python 2.7 and 3.5.
|
||||||
|
|
||||||
|
New Features:
|
||||||
|
|
||||||
|
* Allow ``py::args`` to be followed by other arguments; the remaining arguments
|
||||||
|
are implicitly keyword-only, as if a ``py::kw_only{}`` annotation had been
|
||||||
|
used.
|
||||||
|
`#3402 <https://github.com/pybind/pybind11/pull/3402>`_
|
||||||
|
|
||||||
|
* Add C++ Exception type to throw and catch ``AttributeError``. Useful for
|
||||||
|
defining custom ``__setattr__`` and ``__getattr__`` methods.
|
||||||
|
`#3387 <https://github.com/pybind/pybind11/pull/3387>`_
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
|
||||||
|
* Make str/bytes/memoryview more interoperable with ``std::string_view``.
|
||||||
|
`#3521 <https://github.com/pybind/pybind11/pull/3521>`_
|
||||||
|
|
||||||
|
* Replace ``_`` with ``const_name`` in internals, avoid defining ``pybind::_``
|
||||||
|
if ``_`` defined as macro (common gettext usage)
|
||||||
|
`#3423 <https://github.com/pybind/pybind11/pull/3423>`_
|
||||||
|
|
||||||
|
|
||||||
|
Bug fixes:
|
||||||
|
|
||||||
|
* Fix a regression in 2.8.0 that caused undefined behavior (typically
|
||||||
|
segfaults) in ``make_key_iterator``/``make_value_iterator`` if dereferencing
|
||||||
|
the iterator returned a temporary value instead of a reference.
|
||||||
|
`#3348 <https://github.com/pybind/pybind11/pull/3348>`_
|
||||||
|
|
||||||
|
* Fix a rare warning about extra copy in an Eigen constructor.
|
||||||
|
`#3486 <https://github.com/pybind/pybind11/pull/3486>`_
|
||||||
|
|
||||||
|
* Fix caching of the C++ overrides.
|
||||||
|
`#3465 <https://github.com/pybind/pybind11/pull/3465>`_
|
||||||
|
|
||||||
|
* Add missing ``std::forward`` calls to some ``cpp_function`` overloads.
|
||||||
|
`#3443 <https://github.com/pybind/pybind11/pull/3443>`_
|
||||||
|
|
||||||
|
* Support PyPy 7.3.7 and the PyPy3.8 beta. Test python-3.11 on PRs with the
|
||||||
|
``python dev`` label.
|
||||||
|
`#3419 <https://github.com/pybind/pybind11/pull/3419>`_
|
||||||
|
|
||||||
|
* Fix 2.8.0 regression with MSVC 2017 + C++17 mode + Python 3.
|
||||||
|
`#3407 <https://github.com/pybind/pybind11/pull/3407>`_
|
||||||
|
|
||||||
|
* Modernize usage of ``PyCodeObject`` on Python 3.9 (toward supporting Python
|
||||||
|
3.11a1)
|
||||||
|
`#3368 <https://github.com/pybind/pybind11/pull/3368>`_
|
||||||
|
|
||||||
|
* A long-standing bug in eigen.h was fixed (originally PR #3343). The bug was
|
||||||
|
unmasked by newly added ``static_assert``'s in the Eigen 3.4.0 release.
|
||||||
|
`#3352 <https://github.com/pybind/pybind11/pull/3352>`_
|
||||||
|
|
||||||
|
* Replace usage of deprecated ``Eigen::MappedSparseMatrix`` with
|
||||||
|
``Eigen::Map<Eigen::SparseMatrix<...>>`` for Eigen 3.3+.
|
||||||
|
`#3499 <https://github.com/pybind/pybind11/pull/3499>`_
|
||||||
|
|
||||||
|
* Fixed the potential for dangling references when using properties with
|
||||||
|
``std::optional`` types.
|
||||||
|
`#3376 <https://github.com/pybind/pybind11/pull/3376>`_
|
||||||
|
|
||||||
|
* Tweaks to support Microsoft Visual Studio 2022.
|
||||||
|
`#3497 <https://github.com/pybind/pybind11/pull/3497>`_
|
||||||
|
|
||||||
|
Build system improvements:
|
||||||
|
|
||||||
|
* Nicer CMake printout and IDE organisation for pybind11's own tests.
|
||||||
|
`#3479 <https://github.com/pybind/pybind11/pull/3479>`_
|
||||||
|
|
||||||
|
* CMake: report version type as part of the version string to avoid a spurious
|
||||||
|
space in the package status message.
|
||||||
|
`#3472 <https://github.com/pybind/pybind11/pull/3472>`_
|
||||||
|
|
||||||
|
* Support multiple raw inclusion of CMake helper files (Conan.io does this for
|
||||||
|
multi-config generators).
|
||||||
|
`#3420 <https://github.com/pybind/pybind11/pull/3420>`_
|
||||||
|
|
||||||
|
* Fix harmless warning on CMake 3.22.
|
||||||
|
`#3368 <https://github.com/pybind/pybind11/pull/3368>`_
|
||||||
|
|
||||||
|
* Flags starting with ``-g`` in ``$CFLAGS`` and ``$CPPFLAGS`` are no longer
|
||||||
|
overridden by ``.Pybind11Extension``.
|
||||||
|
`#3436 <https://github.com/pybind/pybind11/pull/3436>`_
|
||||||
|
|
||||||
|
* Ensure ThreadPool is closed in ``setup_helpers``.
|
||||||
|
`#3548 <https://github.com/pybind/pybind11/pull/3548>`_
|
||||||
|
|
||||||
|
* Avoid LTS on ``mips64`` and ``ppc64le`` (reported broken).
|
||||||
|
`#3557 <https://github.com/pybind/pybind11/pull/3557>`_
|
||||||
|
|
||||||
|
|
||||||
v2.8.1 (Oct 27, 2021)
|
v2.8.1 (Oct 27, 2021)
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -22,6 +22,9 @@ the version just below.
|
|||||||
To release a new version of pybind11:
|
To release a new version of pybind11:
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
If you don't have nox, you should either use ``pipx run nox`` instead, or use
|
||||||
|
``pipx install nox`` or ``brew install nox`` (Unix).
|
||||||
|
|
||||||
- Update the version number
|
- Update the version number
|
||||||
- Update ``PYBIND11_VERSION_MAJOR`` etc. in
|
- Update ``PYBIND11_VERSION_MAJOR`` etc. in
|
||||||
``include/pybind11/detail/common.h``. PATCH should be a simple integer.
|
``include/pybind11/detail/common.h``. PATCH should be a simple integer.
|
||||||
@ -51,14 +54,12 @@ To release a new version of pybind11:
|
|||||||
notifications to users watching releases, and also uploads PyPI packages).
|
notifications to users watching releases, and also uploads PyPI packages).
|
||||||
(Note: if you do not use an existing tag, this creates a new lightweight tag
|
(Note: if you do not use an existing tag, this creates a new lightweight tag
|
||||||
for you, so you could skip the above step.)
|
for you, so you could skip the above step.)
|
||||||
|
|
||||||
- GUI method: Under `releases <https://github.com/pybind/pybind11/releases>`_
|
- GUI method: Under `releases <https://github.com/pybind/pybind11/releases>`_
|
||||||
click "Draft a new release" on the far right, fill in the tag name
|
click "Draft a new release" on the far right, fill in the tag name
|
||||||
(if you didn't tag above, it will be made here), fill in a release name
|
(if you didn't tag above, it will be made here), fill in a release name
|
||||||
like "Version X.Y.Z", and copy-and-paste the markdown-formatted (!) changelog
|
like "Version X.Y.Z", and copy-and-paste the markdown-formatted (!) changelog
|
||||||
into the description (usually ``cat docs/changelog.rst | pandoc -f rst -t gfm``).
|
into the description (usually ``cat docs/changelog.rst | pandoc -f rst -t gfm``).
|
||||||
Check "pre-release" if this is a beta/RC.
|
Check "pre-release" if this is a beta/RC.
|
||||||
|
|
||||||
- CLI method: with ``gh`` installed, run ``gh release create vX.Y.Z -t "Version X.Y.Z"``
|
- CLI method: with ``gh`` installed, run ``gh release create vX.Y.Z -t "Version X.Y.Z"``
|
||||||
If this is a pre-release, add ``-p``.
|
If this is a pre-release, add ``-p``.
|
||||||
|
|
||||||
@ -90,9 +91,7 @@ If you need to manually upload releases, you can download the releases from the
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
python3 -m pip install build
|
nox -s build
|
||||||
python3 -m build
|
|
||||||
PYBIND11_SDIST_GLOBAL=1 python3 -m build
|
|
||||||
twine upload dist/*
|
twine upload dist/*
|
||||||
|
|
||||||
This makes SDists and wheels, and the final line uploads them.
|
This makes SDists and wheels, and the final line uploads them.
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
breathe==4.26.1
|
breathe==4.31.0
|
||||||
# docutils 0.17 breaks HTML tags & RTD theme
|
sphinx==3.5.4
|
||||||
# https://github.com/sphinx-doc/sphinx/issues/9001
|
sphinx_rtd_theme==1.0.0
|
||||||
docutils==0.16
|
sphinxcontrib-moderncmakedomain==3.19
|
||||||
sphinx==3.3.1
|
sphinxcontrib-svg2pdfconverter==1.1.1
|
||||||
sphinx_rtd_theme==0.5.0
|
|
||||||
sphinxcontrib-moderncmakedomain==3.17
|
|
||||||
sphinxcontrib-svg2pdfconverter==1.1.0
|
|
||||||
|
@ -17,6 +17,10 @@ v2.9
|
|||||||
converted to using ``py::module_::import("types").attr("SimpleNamespace")``
|
converted to using ``py::module_::import("types").attr("SimpleNamespace")``
|
||||||
instead.
|
instead.
|
||||||
|
|
||||||
|
* The use of ``_`` in custom type casters can now be replaced with the more
|
||||||
|
readable ``const_name`` instead. The old ``_`` shortcut has been retained
|
||||||
|
unless it is being used as a macro (like for gettext).
|
||||||
|
|
||||||
|
|
||||||
.. _upgrade-guide-2.7:
|
.. _upgrade-guide-2.7:
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ struct function_record {
|
|||||||
function_record()
|
function_record()
|
||||||
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
|
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
|
||||||
is_operator(false), is_method(false), has_args(false),
|
is_operator(false), is_method(false), has_args(false),
|
||||||
has_kwargs(false), has_kw_only_args(false), prepend(false) { }
|
has_kwargs(false), prepend(false) { }
|
||||||
|
|
||||||
/// Function name
|
/// Function name
|
||||||
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
||||||
@ -221,17 +221,15 @@ struct function_record {
|
|||||||
/// True if the function has a '**kwargs' argument
|
/// True if the function has a '**kwargs' argument
|
||||||
bool has_kwargs : 1;
|
bool has_kwargs : 1;
|
||||||
|
|
||||||
/// True once a 'py::kw_only' is encountered (any following args are keyword-only)
|
|
||||||
bool has_kw_only_args : 1;
|
|
||||||
|
|
||||||
/// True if this function is to be inserted at the beginning of the overload resolution chain
|
/// True if this function is to be inserted at the beginning of the overload resolution chain
|
||||||
bool prepend : 1;
|
bool prepend : 1;
|
||||||
|
|
||||||
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
||||||
std::uint16_t nargs;
|
std::uint16_t nargs;
|
||||||
|
|
||||||
/// Number of trailing arguments (counted in `nargs`) that are keyword-only
|
/// Number of leading positional arguments, which are terminated by a py::args or py::kwargs
|
||||||
std::uint16_t nargs_kw_only = 0;
|
/// argument or by a py::kw_only annotation.
|
||||||
|
std::uint16_t nargs_pos = 0;
|
||||||
|
|
||||||
/// Number of leading arguments (counted in `nargs`) that are positional-only
|
/// Number of leading arguments (counted in `nargs`) that are positional-only
|
||||||
std::uint16_t nargs_pos_only = 0;
|
std::uint16_t nargs_pos_only = 0;
|
||||||
@ -411,20 +409,23 @@ template <> struct process_attribute<is_new_style_constructor> : process_attribu
|
|||||||
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
|
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void process_kw_only_arg(const arg &a, function_record *r) {
|
inline void check_kw_only_arg(const arg &a, function_record *r) {
|
||||||
if (!a.name || a.name[0] == '\0')
|
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0'))
|
||||||
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
|
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or args() argument");
|
||||||
++r->nargs_kw_only;
|
}
|
||||||
|
|
||||||
|
inline void append_self_arg_if_needed(function_record *r) {
|
||||||
|
if (r->is_method && r->args.empty())
|
||||||
|
r->args.emplace_back("self", nullptr, handle(), /*convert=*/ true, /*none=*/ false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process a keyword argument attribute (*without* a default value)
|
/// Process a keyword argument attribute (*without* a default value)
|
||||||
template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
||||||
static void init(const arg &a, function_record *r) {
|
static void init(const arg &a, function_record *r) {
|
||||||
if (r->is_method && r->args.empty())
|
append_self_arg_if_needed(r);
|
||||||
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
|
|
||||||
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
|
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
|
||||||
|
|
||||||
if (r->has_kw_only_args) process_kw_only_arg(a, r);
|
check_kw_only_arg(a, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -432,7 +433,7 @@ template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
|||||||
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||||
static void init(const arg_v &a, function_record *r) {
|
static void init(const arg_v &a, function_record *r) {
|
||||||
if (r->is_method && r->args.empty())
|
if (r->is_method && r->args.empty())
|
||||||
r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, false /*none not allowed*/);
|
r->args.emplace_back("self", /*descr=*/ nullptr, /*parent=*/ handle(), /*convert=*/ true, /*none=*/ false);
|
||||||
|
|
||||||
if (!a.value) {
|
if (!a.value) {
|
||||||
#if !defined(NDEBUG)
|
#if !defined(NDEBUG)
|
||||||
@ -457,21 +458,28 @@ template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
|||||||
}
|
}
|
||||||
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
|
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
|
||||||
|
|
||||||
if (r->has_kw_only_args) process_kw_only_arg(a, r);
|
check_kw_only_arg(a, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Process a keyword-only-arguments-follow pseudo argument
|
/// Process a keyword-only-arguments-follow pseudo argument
|
||||||
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
||||||
static void init(const kw_only &, function_record *r) {
|
static void init(const kw_only &, function_record *r) {
|
||||||
r->has_kw_only_args = true;
|
append_self_arg_if_needed(r);
|
||||||
|
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size()))
|
||||||
|
pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative argument location (or omit kw_only() entirely)");
|
||||||
|
r->nargs_pos = static_cast<std::uint16_t>(r->args.size());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Process a positional-only-argument maker
|
/// Process a positional-only-argument maker
|
||||||
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
|
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
|
||||||
static void init(const pos_only &, function_record *r) {
|
static void init(const pos_only &, function_record *r) {
|
||||||
|
append_self_arg_if_needed(r);
|
||||||
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
|
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
|
||||||
|
if (r->nargs_pos_only > r->nargs_pos)
|
||||||
|
pybind11_fail("pos_only(): cannot follow a py::args() argument");
|
||||||
|
// It also can't follow a kw_only, but a static_assert in pybind11.h checks that
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -27,23 +27,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if defined(PYBIND11_CPP17)
|
|
||||||
# if defined(__has_include)
|
|
||||||
# if __has_include(<string_view>)
|
|
||||||
# define PYBIND11_HAS_STRING_VIEW
|
|
||||||
# endif
|
|
||||||
# elif defined(_MSC_VER)
|
|
||||||
# define PYBIND11_HAS_STRING_VIEW
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
#ifdef PYBIND11_HAS_STRING_VIEW
|
|
||||||
#include <string_view>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
|
|
||||||
# define PYBIND11_HAS_U8STRING
|
|
||||||
#endif
|
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
@ -150,7 +133,8 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
handle src_or_index = src;
|
handle src_or_index = src;
|
||||||
#if PY_VERSION_HEX < 0x03080000
|
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
|
||||||
|
#if PY_VERSION_HEX < 0x03080000 || defined(PYPY_VERSION)
|
||||||
object index;
|
object index;
|
||||||
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
|
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
|
||||||
index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
|
index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
|
||||||
@ -224,7 +208,7 @@ public:
|
|||||||
return PyLong_FromUnsignedLongLong((unsigned long long) src);
|
return PyLong_FromUnsignedLongLong((unsigned long long) src);
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(T, _<std::is_integral<T>::value>("int", "float"));
|
PYBIND11_TYPE_CASTER(T, const_name<std::is_integral<T>::value>("int", "float"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> struct void_caster {
|
template<typename T> struct void_caster {
|
||||||
@ -237,7 +221,7 @@ public:
|
|||||||
static handle cast(T, return_value_policy /* policy */, handle /* parent */) {
|
static handle cast(T, return_value_policy /* policy */, handle /* parent */) {
|
||||||
return none().inc_ref();
|
return none().inc_ref();
|
||||||
}
|
}
|
||||||
PYBIND11_TYPE_CASTER(T, _("None"));
|
PYBIND11_TYPE_CASTER(T, const_name("None"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> class type_caster<void_type> : public void_caster<void_type> {};
|
template <> class type_caster<void_type> : public void_caster<void_type> {};
|
||||||
@ -280,7 +264,7 @@ public:
|
|||||||
|
|
||||||
template <typename T> using cast_op_type = void*&;
|
template <typename T> using cast_op_type = void*&;
|
||||||
explicit operator void *&() { return value; }
|
explicit operator void *&() { return value; }
|
||||||
static constexpr auto name = _("capsule");
|
static constexpr auto name = const_name("capsule");
|
||||||
private:
|
private:
|
||||||
void *value = nullptr;
|
void *value = nullptr;
|
||||||
};
|
};
|
||||||
@ -331,7 +315,7 @@ public:
|
|||||||
static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) {
|
static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) {
|
||||||
return handle(src ? Py_True : Py_False).inc_ref();
|
return handle(src ? Py_True : Py_False).inc_ref();
|
||||||
}
|
}
|
||||||
PYBIND11_TYPE_CASTER(bool, _("bool"));
|
PYBIND11_TYPE_CASTER(bool, const_name("bool"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper class for UTF-{8,16,32} C++ stl strings:
|
// Helper class for UTF-{8,16,32} C++ stl strings:
|
||||||
@ -421,7 +405,7 @@ template <typename StringType, bool IsView = false> struct string_caster {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(StringType, _(PYBIND11_STRING_NAME));
|
PYBIND11_TYPE_CASTER(StringType, const_name(PYBIND11_STRING_NAME));
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static handle decode_utfN(const char *buffer, ssize_t nbytes) {
|
static handle decode_utfN(const char *buffer, ssize_t nbytes) {
|
||||||
@ -558,7 +542,7 @@ public:
|
|||||||
return one_char;
|
return one_char;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto name = _(PYBIND11_STRING_NAME);
|
static constexpr auto name = const_name(PYBIND11_STRING_NAME);
|
||||||
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
|
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -595,7 +579,7 @@ public:
|
|||||||
return cast(*src, policy, parent);
|
return cast(*src, policy, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto name = _("Tuple[") + concat(make_caster<Ts>::name...) + _("]");
|
static constexpr auto name = const_name("Tuple[") + concat(make_caster<Ts>::name...) + const_name("]");
|
||||||
|
|
||||||
template <typename T> using cast_op_type = type;
|
template <typename T> using cast_op_type = type;
|
||||||
|
|
||||||
@ -780,14 +764,14 @@ template <typename base, typename holder> struct is_holder_type :
|
|||||||
template <typename base, typename deleter> struct is_holder_type<base, std::unique_ptr<base, deleter>> :
|
template <typename base, typename deleter> struct is_holder_type<base, std::unique_ptr<base, deleter>> :
|
||||||
std::true_type {};
|
std::true_type {};
|
||||||
|
|
||||||
template <typename T> struct handle_type_name { static constexpr auto name = _<T>(); };
|
template <typename T> struct handle_type_name { static constexpr auto name = const_name<T>(); };
|
||||||
template <> struct handle_type_name<bytes> { static constexpr auto name = _(PYBIND11_BYTES_NAME); };
|
template <> struct handle_type_name<bytes> { static constexpr auto name = const_name(PYBIND11_BYTES_NAME); };
|
||||||
template <> struct handle_type_name<int_> { static constexpr auto name = _("int"); };
|
template <> struct handle_type_name<int_> { static constexpr auto name = const_name("int"); };
|
||||||
template <> struct handle_type_name<iterable> { static constexpr auto name = _("Iterable"); };
|
template <> struct handle_type_name<iterable> { static constexpr auto name = const_name("Iterable"); };
|
||||||
template <> struct handle_type_name<iterator> { static constexpr auto name = _("Iterator"); };
|
template <> struct handle_type_name<iterator> { static constexpr auto name = const_name("Iterator"); };
|
||||||
template <> struct handle_type_name<none> { static constexpr auto name = _("None"); };
|
template <> struct handle_type_name<none> { static constexpr auto name = const_name("None"); };
|
||||||
template <> struct handle_type_name<args> { static constexpr auto name = _("*args"); };
|
template <> struct handle_type_name<args> { static constexpr auto name = const_name("*args"); };
|
||||||
template <> struct handle_type_name<kwargs> { static constexpr auto name = _("**kwargs"); };
|
template <> struct handle_type_name<kwargs> { static constexpr auto name = const_name("**kwargs"); };
|
||||||
|
|
||||||
template <typename type>
|
template <typename type>
|
||||||
struct pyobject_caster {
|
struct pyobject_caster {
|
||||||
@ -1130,6 +1114,9 @@ constexpr arg operator"" _a(const char *name, size_t) { return arg(name); }
|
|||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
template <typename T> using is_kw_only = std::is_same<intrinsic_t<T>, kw_only>;
|
||||||
|
template <typename T> using is_pos_only = std::is_same<intrinsic_t<T>, pos_only>;
|
||||||
|
|
||||||
// forward declaration (definition in attr.h)
|
// forward declaration (definition in attr.h)
|
||||||
struct function_record;
|
struct function_record;
|
||||||
|
|
||||||
@ -1165,17 +1152,18 @@ class argument_loader {
|
|||||||
|
|
||||||
template <typename Arg> using argument_is_args = std::is_same<intrinsic_t<Arg>, args>;
|
template <typename Arg> using argument_is_args = std::is_same<intrinsic_t<Arg>, args>;
|
||||||
template <typename Arg> using argument_is_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
|
template <typename Arg> using argument_is_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
|
||||||
// Get args/kwargs argument positions relative to the end of the argument list:
|
// Get kwargs argument position, or -1 if not present:
|
||||||
static constexpr auto args_pos = constexpr_first<argument_is_args, Args...>() - (int) sizeof...(Args),
|
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
|
||||||
kwargs_pos = constexpr_first<argument_is_kwargs, Args...>() - (int) sizeof...(Args);
|
|
||||||
|
|
||||||
static constexpr bool args_kwargs_are_last = kwargs_pos >= - 1 && args_pos >= kwargs_pos - 1;
|
static_assert(kwargs_pos == -1 || kwargs_pos == (int) sizeof...(Args) - 1, "py::kwargs is only permitted as the last argument of a function");
|
||||||
|
|
||||||
static_assert(args_kwargs_are_last, "py::args/py::kwargs are only permitted as the last argument(s) of a function");
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr bool has_kwargs = kwargs_pos < 0;
|
static constexpr bool has_kwargs = kwargs_pos != -1;
|
||||||
static constexpr bool has_args = args_pos < 0;
|
|
||||||
|
// py::args argument position; -1 if not present.
|
||||||
|
static constexpr int args_pos = constexpr_last<argument_is_args, Args...>();
|
||||||
|
|
||||||
|
static_assert(args_pos == -1 || args_pos == constexpr_first<argument_is_args, Args...>(), "py::args cannot be specified more than once");
|
||||||
|
|
||||||
static constexpr auto arg_names = concat(type_descr(make_caster<Args>::name)...);
|
static constexpr auto arg_names = concat(type_descr(make_caster<Args>::name)...);
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
return PyDelta_FromDSU(dd.count(), ss.count(), us.count());
|
return PyDelta_FromDSU(dd.count(), ss.count(), us.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(type, _("datetime.timedelta"));
|
PYBIND11_TYPE_CASTER(type, const_name("datetime.timedelta"));
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) {
|
inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) {
|
||||||
@ -195,7 +195,7 @@ public:
|
|||||||
localtime.tm_sec,
|
localtime.tm_sec,
|
||||||
us.count());
|
us.count());
|
||||||
}
|
}
|
||||||
PYBIND11_TYPE_CASTER(type, _("datetime.datetime"));
|
PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Other clocks that are not the system clock are not measured as datetime.datetime objects
|
// Other clocks that are not the system clock are not measured as datetime.datetime objects
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(std::complex<T>, _("complex"));
|
PYBIND11_TYPE_CASTER(std::complex<T>, const_name("complex"));
|
||||||
};
|
};
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||||
|
@ -10,12 +10,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PYBIND11_VERSION_MAJOR 2
|
#define PYBIND11_VERSION_MAJOR 2
|
||||||
#define PYBIND11_VERSION_MINOR 8
|
#define PYBIND11_VERSION_MINOR 9
|
||||||
#define PYBIND11_VERSION_PATCH 1
|
#define PYBIND11_VERSION_PATCH 0
|
||||||
|
|
||||||
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
|
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
|
||||||
// Additional convention: 0xD = dev
|
// Additional convention: 0xD = dev
|
||||||
#define PYBIND11_VERSION_HEX 0x02080100
|
#define PYBIND11_VERSION_HEX 0x02090000
|
||||||
|
|
||||||
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name {
|
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name {
|
||||||
#define PYBIND11_NAMESPACE_END(name) }
|
#define PYBIND11_NAMESPACE_END(name) }
|
||||||
@ -154,6 +154,14 @@
|
|||||||
// C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
|
// C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
|
||||||
# pragma warning(disable: 4505)
|
# pragma warning(disable: 4505)
|
||||||
# if defined(_DEBUG) && !defined(Py_DEBUG)
|
# if defined(_DEBUG) && !defined(Py_DEBUG)
|
||||||
|
// Workaround for a VS 2022 issue.
|
||||||
|
// NOTE: This workaround knowingly violates the Python.h include order requirement:
|
||||||
|
// https://docs.python.org/3/c-api/intro.html#include-files
|
||||||
|
// See https://github.com/pybind/pybind11/pull/3497 for full context.
|
||||||
|
# include <yvals.h>
|
||||||
|
# if _MSVC_STL_VERSION >= 143
|
||||||
|
# include <crtdefs.h>
|
||||||
|
# endif
|
||||||
# define PYBIND11_DEBUG_MARKER
|
# define PYBIND11_DEBUG_MARKER
|
||||||
# undef _DEBUG
|
# undef _DEBUG
|
||||||
# endif
|
# endif
|
||||||
@ -183,6 +191,21 @@
|
|||||||
# define PYBIND11_HAS_VARIANT 1
|
# define PYBIND11_HAS_VARIANT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(PYBIND11_CPP17)
|
||||||
|
# if defined(__has_include)
|
||||||
|
# if __has_include(<string_view>)
|
||||||
|
# define PYBIND11_HAS_STRING_VIEW
|
||||||
|
# endif
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# define PYBIND11_HAS_STRING_VIEW
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
|
||||||
|
# define PYBIND11_HAS_U8STRING
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#include <frameobject.h>
|
#include <frameobject.h>
|
||||||
#include <pythread.h>
|
#include <pythread.h>
|
||||||
|
@ -54,8 +54,8 @@ constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, c
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N>
|
template <size_t N>
|
||||||
constexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); }
|
constexpr descr<N - 1> const_name(char const(&text)[N]) { return descr<N - 1>(text); }
|
||||||
constexpr descr<0> _(char const(&)[1]) { return {}; }
|
constexpr descr<0> const_name(char const(&)[1]) { return {}; }
|
||||||
|
|
||||||
template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
|
template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
|
||||||
template <size_t...Digits> struct int_to_str<0, Digits...> {
|
template <size_t...Digits> struct int_to_str<0, Digits...> {
|
||||||
@ -64,25 +64,50 @@ template <size_t...Digits> struct int_to_str<0, Digits...> {
|
|||||||
|
|
||||||
// Ternary description (like std::conditional)
|
// Ternary description (like std::conditional)
|
||||||
template <bool B, size_t N1, size_t N2>
|
template <bool B, size_t N1, size_t N2>
|
||||||
constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) {
|
constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const(&text1)[N1], char const(&)[N2]) {
|
||||||
return _(text1);
|
return const_name(text1);
|
||||||
}
|
}
|
||||||
template <bool B, size_t N1, size_t N2>
|
template <bool B, size_t N1, size_t N2>
|
||||||
constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) {
|
constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const(&)[N1], char const(&text2)[N2]) {
|
||||||
return _(text2);
|
return const_name(text2);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool B, typename T1, typename T2>
|
template <bool B, typename T1, typename T2>
|
||||||
constexpr enable_if_t<B, T1> _(const T1 &d, const T2 &) { return d; }
|
constexpr enable_if_t<B, T1> const_name(const T1 &d, const T2 &) { return d; }
|
||||||
template <bool B, typename T1, typename T2>
|
template <bool B, typename T1, typename T2>
|
||||||
constexpr enable_if_t<!B, T2> _(const T1 &, const T2 &d) { return d; }
|
constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) { return d; }
|
||||||
|
|
||||||
template <size_t Size>
|
template <size_t Size>
|
||||||
auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
||||||
return int_to_str<Size / 10, Size % 10>::digits;
|
return int_to_str<Size / 10, Size % 10>::digits;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type> constexpr descr<1, Type> _() { return {'%'}; }
|
template <typename Type> constexpr descr<1, Type> const_name() { return {'%'}; }
|
||||||
|
|
||||||
|
// The "_" might be defined as a macro - don't define it if so.
|
||||||
|
// Repeating the const_name code to avoid introducing a #define.
|
||||||
|
#ifndef _
|
||||||
|
template <size_t N>
|
||||||
|
constexpr descr<N-1> _(char const(&text)[N]) { return const_name<N>(text); }
|
||||||
|
template <bool B, size_t N1, size_t N2>
|
||||||
|
constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&text2)[N2]) {
|
||||||
|
return const_name<B,N1,N2>(text1, text2);
|
||||||
|
}
|
||||||
|
template <bool B, size_t N1, size_t N2>
|
||||||
|
constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&text1)[N1], char const(&text2)[N2]) {
|
||||||
|
return const_name<B,N1,N2>(text1, text2);
|
||||||
|
}
|
||||||
|
template <bool B, typename T1, typename T2>
|
||||||
|
constexpr enable_if_t<B, T1> _(const T1 &d1, const T2 &d2) { return const_name<B,T1,T2>(d1, d2); }
|
||||||
|
template <bool B, typename T1, typename T2>
|
||||||
|
constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) { return const_name<B,T1,T2>(d1, d2); }
|
||||||
|
|
||||||
|
template <size_t Size>
|
||||||
|
auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
||||||
|
return const_name<Size>();
|
||||||
|
}
|
||||||
|
template <typename Type> constexpr descr<1, Type> _() { return const_name<Type>(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
constexpr descr<0> concat() { return {}; }
|
constexpr descr<0> concat() { return {}; }
|
||||||
|
|
||||||
@ -92,12 +117,12 @@ constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; }
|
|||||||
template <size_t N, typename... Ts, typename... Args>
|
template <size_t N, typename... Ts, typename... Args>
|
||||||
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
|
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
|
||||||
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
|
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
|
||||||
return d + _(", ") + concat(args...);
|
return d + const_name(", ") + concat(args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <size_t N, typename... Ts>
|
template <size_t N, typename... Ts>
|
||||||
constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
|
constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
|
||||||
return _("{") + descr + _("}");
|
return const_name("{") + descr + const_name("}");
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
@ -24,7 +24,7 @@ public:
|
|||||||
|
|
||||||
template <typename> using cast_op_type = value_and_holder &;
|
template <typename> using cast_op_type = value_and_holder &;
|
||||||
explicit operator value_and_holder &() { return *value; }
|
explicit operator value_and_holder &() { return *value; }
|
||||||
static constexpr auto name = _<value_and_holder>();
|
static constexpr auto name = const_name<value_and_holder>();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
value_and_holder *value = nullptr;
|
value_and_holder *value = nullptr;
|
||||||
|
@ -897,7 +897,7 @@ template <typename type> class type_caster_base : public type_caster_generic {
|
|||||||
using itype = intrinsic_t<type>;
|
using itype = intrinsic_t<type>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = _<type>();
|
static constexpr auto name = const_name<type>();
|
||||||
|
|
||||||
type_caster_base() : type_caster_base(typeid(type)) { }
|
type_caster_base() : type_caster_base(typeid(type)) { }
|
||||||
explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) { }
|
explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) { }
|
||||||
|
@ -50,8 +50,12 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
|||||||
|
|
||||||
#if EIGEN_VERSION_AT_LEAST(3,3,0)
|
#if EIGEN_VERSION_AT_LEAST(3,3,0)
|
||||||
using EigenIndex = Eigen::Index;
|
using EigenIndex = Eigen::Index;
|
||||||
|
template<typename Scalar, int Flags, typename StorageIndex>
|
||||||
|
using EigenMapSparseMatrix = Eigen::Map<Eigen::SparseMatrix<Scalar, Flags, StorageIndex>>;
|
||||||
#else
|
#else
|
||||||
using EigenIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
|
using EigenIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
|
||||||
|
template<typename Scalar, int Flags, typename StorageIndex>
|
||||||
|
using EigenMapSparseMatrix = Eigen::MappedSparseMatrix<Scalar, Flags, StorageIndex>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Matches Eigen::Map, Eigen::Ref, blocks, etc:
|
// Matches Eigen::Map, Eigen::Ref, blocks, etc:
|
||||||
@ -80,14 +84,12 @@ template <bool EigenRowMajor> struct EigenConformable {
|
|||||||
// Matrix type:
|
// Matrix type:
|
||||||
EigenConformable(EigenIndex r, EigenIndex c,
|
EigenConformable(EigenIndex r, EigenIndex c,
|
||||||
EigenIndex rstride, EigenIndex cstride) :
|
EigenIndex rstride, EigenIndex cstride) :
|
||||||
conformable{true}, rows{r}, cols{c} {
|
conformable{true}, rows{r}, cols{c},
|
||||||
// TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity. http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747
|
//TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity. http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747
|
||||||
if (rstride < 0 || cstride < 0) {
|
stride{EigenRowMajor ? (rstride > 0 ? rstride : 0) : (cstride > 0 ? cstride : 0) /* outer stride */,
|
||||||
negativestrides = true;
|
EigenRowMajor ? (cstride > 0 ? cstride : 0) : (rstride > 0 ? rstride : 0) /* inner stride */ },
|
||||||
} else {
|
negativestrides{rstride < 0 || cstride < 0} {
|
||||||
stride = {EigenRowMajor ? rstride : cstride /* outer stride */,
|
|
||||||
EigenRowMajor ? cstride : rstride /* inner stride */ };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Vector type:
|
// Vector type:
|
||||||
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex stride)
|
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex stride)
|
||||||
@ -190,20 +192,20 @@ template <typename Type_> struct EigenProps {
|
|||||||
static constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;
|
static constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;
|
||||||
|
|
||||||
static constexpr auto descriptor =
|
static constexpr auto descriptor =
|
||||||
_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
|
const_name("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
|
||||||
_("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) +
|
const_name("[") + const_name<fixed_rows>(const_name<(size_t) rows>(), const_name("m")) +
|
||||||
_(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) +
|
const_name(", ") + const_name<fixed_cols>(const_name<(size_t) cols>(), const_name("n")) +
|
||||||
_("]") +
|
const_name("]") +
|
||||||
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be
|
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be
|
||||||
// satisfied: writeable=True (for a mutable reference), and, depending on the map's stride
|
// satisfied: writeable=True (for a mutable reference), and, depending on the map's stride
|
||||||
// options, possibly f_contiguous or c_contiguous. We include them in the descriptor output
|
// options, possibly f_contiguous or c_contiguous. We include them in the descriptor output
|
||||||
// to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to
|
// to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to
|
||||||
// see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you
|
// see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you
|
||||||
// *gave* a numpy.ndarray of the right type and dimensions.
|
// *gave* a numpy.ndarray of the right type and dimensions.
|
||||||
_<show_writeable>(", flags.writeable", "") +
|
const_name<show_writeable>(", flags.writeable", "") +
|
||||||
_<show_c_contiguous>(", flags.c_contiguous", "") +
|
const_name<show_c_contiguous>(", flags.c_contiguous", "") +
|
||||||
_<show_f_contiguous>(", flags.f_contiguous", "") +
|
const_name<show_f_contiguous>(", flags.f_contiguous", "") +
|
||||||
_("]");
|
const_name("]");
|
||||||
};
|
};
|
||||||
|
|
||||||
// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
|
// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
|
||||||
@ -573,9 +575,9 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
|||||||
if (!values || !innerIndices || !outerIndices)
|
if (!values || !innerIndices || !outerIndices)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
value = Eigen::MappedSparseMatrix<Scalar,
|
value = EigenMapSparseMatrix<Scalar,
|
||||||
Type::Flags & (Eigen::RowMajor | Eigen::ColMajor),
|
Type::Flags & (Eigen::RowMajor | Eigen::ColMajor),
|
||||||
StorageIndex>(
|
StorageIndex>(
|
||||||
shape[0].cast<Index>(), shape[1].cast<Index>(), nnz,
|
shape[0].cast<Index>(), shape[1].cast<Index>(), nnz,
|
||||||
outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data());
|
outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data());
|
||||||
|
|
||||||
@ -598,8 +600,8 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
|||||||
).release();
|
).release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(Type, _<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
|
PYBIND11_TYPE_CASTER(Type, const_name<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
|
||||||
+ npy_format_descriptor<Scalar>::name + _("]"));
|
+ npy_format_descriptor<Scalar>::name + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
@ -102,6 +102,13 @@ inline wchar_t *widen_chars(const char *safe_arg) {
|
|||||||
wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
|
wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
|
||||||
#else
|
#else
|
||||||
wchar_t *widened_arg = nullptr;
|
wchar_t *widened_arg = nullptr;
|
||||||
|
|
||||||
|
// warning C4996: 'mbstowcs': This function or variable may be unsafe.
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable:4996)
|
||||||
|
#endif
|
||||||
|
|
||||||
# if defined(HAVE_BROKEN_MBSTOWCS) && HAVE_BROKEN_MBSTOWCS
|
# if defined(HAVE_BROKEN_MBSTOWCS) && HAVE_BROKEN_MBSTOWCS
|
||||||
size_t count = strlen(safe_arg);
|
size_t count = strlen(safe_arg);
|
||||||
# else
|
# else
|
||||||
@ -111,6 +118,11 @@ inline wchar_t *widen_chars(const char *safe_arg) {
|
|||||||
widened_arg = new wchar_t[count + 1];
|
widened_arg = new wchar_t[count + 1];
|
||||||
mbstowcs(widened_arg, safe_arg, count + 1);
|
mbstowcs(widened_arg, safe_arg, count + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
return widened_arg;
|
return widened_arg;
|
||||||
}
|
}
|
||||||
|
@ -19,11 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
|||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
inline void ensure_builtins_in_globals(object &global) {
|
inline void ensure_builtins_in_globals(object &global) {
|
||||||
#if PY_VERSION_HEX < 0x03080000
|
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000
|
||||||
// Running exec and eval on Python 2 and 3 adds `builtins` module under
|
// Running exec and eval on Python 2 and 3 adds `builtins` module under
|
||||||
// `__builtins__` key to globals if not yet present.
|
// `__builtins__` key to globals if not yet present.
|
||||||
// Python 3.8 made PyRun_String behave similarly. Let's also do that for
|
// Python 3.8 made PyRun_String behave similarly. Let's also do that for
|
||||||
// older versions, for consistency.
|
// older versions, for consistency. This was missing from PyPy3.8 7.3.7.
|
||||||
if (!global.contains("__builtins__"))
|
if (!global.contains("__builtins__"))
|
||||||
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
|
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
|
||||||
#else
|
#else
|
||||||
|
@ -113,8 +113,8 @@ public:
|
|||||||
return cpp_function(std::forward<Func>(f_), policy).release();
|
return cpp_function(std::forward<Func>(f_), policy).release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(type, _("Callable[[") + concat(make_caster<Args>::name...) + _("], ")
|
PYBIND11_TYPE_CASTER(type, const_name("Callable[[") + concat(make_caster<Args>::name...) + const_name("], ")
|
||||||
+ make_caster<retval_type>::name + _("]"));
|
+ make_caster<retval_type>::name + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
@ -39,7 +39,7 @@ class array; // Forward declaration
|
|||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
template <> struct handle_type_name<array> { static constexpr auto name = _("numpy.ndarray"); };
|
template <> struct handle_type_name<array> { static constexpr auto name = const_name("numpy.ndarray"); };
|
||||||
|
|
||||||
template <typename type, typename SFINAE = void> struct npy_format_descriptor;
|
template <typename type, typename SFINAE = void> struct npy_format_descriptor;
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ template <typename T> struct array_info_scalar {
|
|||||||
using type = T;
|
using type = T;
|
||||||
static constexpr bool is_array = false;
|
static constexpr bool is_array = false;
|
||||||
static constexpr bool is_empty = false;
|
static constexpr bool is_empty = false;
|
||||||
static constexpr auto extents = _("");
|
static constexpr auto extents = const_name("");
|
||||||
static void append_extents(list& /* shape */) { }
|
static void append_extents(list& /* shape */) { }
|
||||||
};
|
};
|
||||||
// Computes underlying type and a comma-separated list of extents for array
|
// Computes underlying type and a comma-separated list of extents for array
|
||||||
@ -309,8 +309,8 @@ template <typename T, size_t N> struct array_info<std::array<T, N>> {
|
|||||||
array_info<T>::append_extents(shape);
|
array_info<T>::append_extents(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto extents = _<array_info<T>::is_array>(
|
static constexpr auto extents = const_name<array_info<T>::is_array>(
|
||||||
concat(_<N>(), array_info<T>::extents), _<N>()
|
concat(const_name<N>(), array_info<T>::extents), const_name<N>()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
// For numpy we have special handling for arrays of characters, so we don't include
|
// For numpy we have special handling for arrays of characters, so we don't include
|
||||||
@ -1021,7 +1021,7 @@ template <typename T>
|
|||||||
struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
|
struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
|
||||||
static std::string format() {
|
static std::string format() {
|
||||||
using namespace detail;
|
using namespace detail;
|
||||||
static constexpr auto extents = _("(") + array_info<T>::extents + _(")");
|
static constexpr auto extents = const_name("(") + array_info<T>::extents + const_name(")");
|
||||||
return extents.text + format_descriptor<remove_all_extents_t<T>>::format();
|
return extents.text + format_descriptor<remove_all_extents_t<T>>::format();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1056,28 +1056,28 @@ struct npy_format_descriptor_name;
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
|
struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
|
||||||
static constexpr auto name = _<std::is_same<T, bool>::value>(
|
static constexpr auto name = const_name<std::is_same<T, bool>::value>(
|
||||||
_("bool"), _<std::is_signed<T>::value>("numpy.int", "numpy.uint") + _<sizeof(T)*8>()
|
const_name("bool"), const_name<std::is_signed<T>::value>("numpy.int", "numpy.uint") + const_name<sizeof(T)*8>()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
|
struct npy_format_descriptor_name<T, enable_if_t<std::is_floating_point<T>::value>> {
|
||||||
static constexpr auto name = _<std::is_same<T, float>::value
|
static constexpr auto name = const_name<std::is_same<T, float>::value
|
||||||
|| std::is_same<T, const float>::value
|
|| std::is_same<T, const float>::value
|
||||||
|| std::is_same<T, double>::value
|
|| std::is_same<T, double>::value
|
||||||
|| std::is_same<T, const double>::value>(
|
|| std::is_same<T, const double>::value>(
|
||||||
_("numpy.float") + _<sizeof(T)*8>(), _("numpy.longdouble")
|
const_name("numpy.float") + const_name<sizeof(T)*8>(), const_name("numpy.longdouble")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct npy_format_descriptor_name<T, enable_if_t<is_complex<T>::value>> {
|
struct npy_format_descriptor_name<T, enable_if_t<is_complex<T>::value>> {
|
||||||
static constexpr auto name = _<std::is_same<typename T::value_type, float>::value
|
static constexpr auto name = const_name<std::is_same<typename T::value_type, float>::value
|
||||||
|| std::is_same<typename T::value_type, const float>::value
|
|| std::is_same<typename T::value_type, const float>::value
|
||||||
|| std::is_same<typename T::value_type, double>::value
|
|| std::is_same<typename T::value_type, double>::value
|
||||||
|| std::is_same<typename T::value_type, const double>::value>(
|
|| std::is_same<typename T::value_type, const double>::value>(
|
||||||
_("numpy.complex") + _<sizeof(typename T::value_type)*16>(), _("numpy.longcomplex")
|
const_name("numpy.complex") + const_name<sizeof(typename T::value_type)*16>(), const_name("numpy.longcomplex")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1105,7 +1105,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define PYBIND11_DECL_CHAR_FMT \
|
#define PYBIND11_DECL_CHAR_FMT \
|
||||||
static constexpr auto name = _("S") + _<N>(); \
|
static constexpr auto name = const_name("S") + const_name<N>(); \
|
||||||
static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); }
|
static pybind11::dtype dtype() { return pybind11::dtype(std::string("S") + std::to_string(N)); }
|
||||||
template <size_t N> struct npy_format_descriptor<char[N]> { PYBIND11_DECL_CHAR_FMT };
|
template <size_t N> struct npy_format_descriptor<char[N]> { PYBIND11_DECL_CHAR_FMT };
|
||||||
template <size_t N> struct npy_format_descriptor<std::array<char, N>> { PYBIND11_DECL_CHAR_FMT };
|
template <size_t N> struct npy_format_descriptor<std::array<char, N>> { PYBIND11_DECL_CHAR_FMT };
|
||||||
@ -1117,7 +1117,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
|
static_assert(!array_info<T>::is_empty, "Zero-sized arrays are not supported");
|
||||||
|
|
||||||
static constexpr auto name = _("(") + array_info<T>::extents + _(")") + base_descr::name;
|
static constexpr auto name = const_name("(") + array_info<T>::extents + const_name(")") + base_descr::name;
|
||||||
static pybind11::dtype dtype() {
|
static pybind11::dtype dtype() {
|
||||||
list shape;
|
list shape;
|
||||||
array_info<T>::append_extents(shape);
|
array_info<T>::append_extents(shape);
|
||||||
@ -1705,7 +1705,7 @@ vectorize_extractor(const Func &f, Return (*) (Args ...)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> {
|
template <typename T, int Flags> struct handle_type_name<array_t<T, Flags>> {
|
||||||
static constexpr auto name = _("numpy.ndarray[") + npy_format_descriptor<T>::name + _("]");
|
static constexpr auto name = const_name("numpy.ndarray[") + npy_format_descriptor<T>::name + const_name("]");
|
||||||
};
|
};
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_END(detail)
|
PYBIND11_NAMESPACE_END(detail)
|
||||||
|
@ -115,7 +115,7 @@ public:
|
|||||||
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) {
|
cpp_function(Return (Class::*f)(Arg...)&, const Extra&... extra) {
|
||||||
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(args...); },
|
initialize([f](Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
|
||||||
(Return (*) (Class *, Arg...)) nullptr, extra...);
|
(Return (*) (Class *, Arg...)) nullptr, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ public:
|
|||||||
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) {
|
cpp_function(Return (Class::*f)(Arg...) const&, const Extra&... extra) {
|
||||||
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(args...); },
|
initialize([f](const Class *c, Arg... args) -> Return { return (c->*f)(std::forward<Arg>(args)...); },
|
||||||
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
|
(Return (*)(const Class *, Arg ...)) nullptr, extra...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,7 +203,7 @@ protected:
|
|||||||
conditional_t<std::is_void<Return>::value, void_type, Return>
|
conditional_t<std::is_void<Return>::value, void_type, Return>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
static_assert(expected_num_args<Extra...>(sizeof...(Args), cast_in::has_args, cast_in::has_kwargs),
|
static_assert(expected_num_args<Extra...>(sizeof...(Args), cast_in::args_pos >= 0, cast_in::has_kwargs),
|
||||||
"The number of argument annotations does not match the number of function arguments");
|
"The number of argument annotations does not match the number of function arguments");
|
||||||
|
|
||||||
/* Dispatch code which converts function arguments and performs the actual function call */
|
/* Dispatch code which converts function arguments and performs the actual function call */
|
||||||
@ -238,30 +238,37 @@ protected:
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rec->nargs_pos = cast_in::args_pos >= 0
|
||||||
|
? static_cast<std::uint16_t>(cast_in::args_pos)
|
||||||
|
: sizeof...(Args) - cast_in::has_kwargs; // Will get reduced more if we have a kw_only
|
||||||
|
rec->has_args = cast_in::args_pos >= 0;
|
||||||
|
rec->has_kwargs = cast_in::has_kwargs;
|
||||||
|
|
||||||
/* Process any user-provided function attributes */
|
/* Process any user-provided function attributes */
|
||||||
process_attributes<Extra...>::init(extra..., rec);
|
process_attributes<Extra...>::init(extra..., rec);
|
||||||
|
|
||||||
{
|
{
|
||||||
constexpr bool has_kw_only_args = any_of<std::is_same<kw_only, Extra>...>::value,
|
constexpr bool has_kw_only_args = any_of<std::is_same<kw_only, Extra>...>::value,
|
||||||
has_pos_only_args = any_of<std::is_same<pos_only, Extra>...>::value,
|
has_pos_only_args = any_of<std::is_same<pos_only, Extra>...>::value,
|
||||||
has_args = any_of<std::is_same<args, Args>...>::value,
|
|
||||||
has_arg_annotations = any_of<is_keyword<Extra>...>::value;
|
has_arg_annotations = any_of<is_keyword<Extra>...>::value;
|
||||||
static_assert(has_arg_annotations || !has_kw_only_args, "py::kw_only requires the use of argument annotations");
|
static_assert(has_arg_annotations || !has_kw_only_args, "py::kw_only requires the use of argument annotations");
|
||||||
static_assert(has_arg_annotations || !has_pos_only_args, "py::pos_only requires the use of argument annotations (for docstrings and aligning the annotations to the argument)");
|
static_assert(has_arg_annotations || !has_pos_only_args, "py::pos_only requires the use of argument annotations (for docstrings and aligning the annotations to the argument)");
|
||||||
static_assert(!(has_args && has_kw_only_args), "py::kw_only cannot be combined with a py::args argument");
|
|
||||||
|
static_assert(constexpr_sum(is_kw_only<Extra>::value...) <= 1, "py::kw_only may be specified only once");
|
||||||
|
static_assert(constexpr_sum(is_pos_only<Extra>::value...) <= 1, "py::pos_only may be specified only once");
|
||||||
|
constexpr auto kw_only_pos = constexpr_first<is_kw_only, Extra...>();
|
||||||
|
constexpr auto pos_only_pos = constexpr_first<is_pos_only, Extra...>();
|
||||||
|
static_assert(!(has_kw_only_args && has_pos_only_args) || pos_only_pos < kw_only_pos, "py::pos_only must come before py::kw_only");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Generate a readable signature describing the function's arguments and return value types */
|
/* Generate a readable signature describing the function's arguments and return value types */
|
||||||
static constexpr auto signature = _("(") + cast_in::arg_names + _(") -> ") + cast_out::name;
|
static constexpr auto signature = const_name("(") + cast_in::arg_names + const_name(") -> ") + cast_out::name;
|
||||||
PYBIND11_DESCR_CONSTEXPR auto types = decltype(signature)::types();
|
PYBIND11_DESCR_CONSTEXPR auto types = decltype(signature)::types();
|
||||||
|
|
||||||
/* Register the function with Python from generic (non-templated) code */
|
/* Register the function with Python from generic (non-templated) code */
|
||||||
// Pass on the ownership over the `unique_rec` to `initialize_generic`. `rec` stays valid.
|
// Pass on the ownership over the `unique_rec` to `initialize_generic`. `rec` stays valid.
|
||||||
initialize_generic(std::move(unique_rec), signature.text, types.data(), sizeof...(Args));
|
initialize_generic(std::move(unique_rec), signature.text, types.data(), sizeof...(Args));
|
||||||
|
|
||||||
if (cast_in::has_args) rec->has_args = true;
|
|
||||||
if (cast_in::has_kwargs) rec->has_kwargs = true;
|
|
||||||
|
|
||||||
/* Stash some additional information used by an important optimization in 'functional.h' */
|
/* Stash some additional information used by an important optimization in 'functional.h' */
|
||||||
using FunctionType = Return (*)(Args...);
|
using FunctionType = Return (*)(Args...);
|
||||||
constexpr bool is_function_ptr =
|
constexpr bool is_function_ptr =
|
||||||
@ -340,16 +347,18 @@ protected:
|
|||||||
/* Generate a proper function signature */
|
/* Generate a proper function signature */
|
||||||
std::string signature;
|
std::string signature;
|
||||||
size_t type_index = 0, arg_index = 0;
|
size_t type_index = 0, arg_index = 0;
|
||||||
|
bool is_starred = false;
|
||||||
for (auto *pc = text; *pc != '\0'; ++pc) {
|
for (auto *pc = text; *pc != '\0'; ++pc) {
|
||||||
const auto c = *pc;
|
const auto c = *pc;
|
||||||
|
|
||||||
if (c == '{') {
|
if (c == '{') {
|
||||||
// Write arg name for everything except *args and **kwargs.
|
// Write arg name for everything except *args and **kwargs.
|
||||||
if (*(pc + 1) == '*')
|
is_starred = *(pc + 1) == '*';
|
||||||
|
if (is_starred)
|
||||||
continue;
|
continue;
|
||||||
// Separator for keyword-only arguments, placed before the kw
|
// Separator for keyword-only arguments, placed before the kw
|
||||||
// arguments start
|
// arguments start (unless we are already putting an *args)
|
||||||
if (rec->nargs_kw_only > 0 && arg_index + rec->nargs_kw_only == args)
|
if (!rec->has_args && arg_index == rec->nargs_pos)
|
||||||
signature += "*, ";
|
signature += "*, ";
|
||||||
if (arg_index < rec->args.size() && rec->args[arg_index].name) {
|
if (arg_index < rec->args.size() && rec->args[arg_index].name) {
|
||||||
signature += rec->args[arg_index].name;
|
signature += rec->args[arg_index].name;
|
||||||
@ -361,7 +370,7 @@ protected:
|
|||||||
signature += ": ";
|
signature += ": ";
|
||||||
} else if (c == '}') {
|
} else if (c == '}') {
|
||||||
// Write default value if available.
|
// Write default value if available.
|
||||||
if (arg_index < rec->args.size() && rec->args[arg_index].descr) {
|
if (!is_starred && arg_index < rec->args.size() && rec->args[arg_index].descr) {
|
||||||
signature += " = ";
|
signature += " = ";
|
||||||
signature += rec->args[arg_index].descr;
|
signature += rec->args[arg_index].descr;
|
||||||
}
|
}
|
||||||
@ -369,7 +378,8 @@ protected:
|
|||||||
// argument, rather than before like *
|
// argument, rather than before like *
|
||||||
if (rec->nargs_pos_only > 0 && (arg_index + 1) == rec->nargs_pos_only)
|
if (rec->nargs_pos_only > 0 && (arg_index + 1) == rec->nargs_pos_only)
|
||||||
signature += ", /";
|
signature += ", /";
|
||||||
arg_index++;
|
if (!is_starred)
|
||||||
|
arg_index++;
|
||||||
} else if (c == '%') {
|
} else if (c == '%') {
|
||||||
const std::type_info *t = types[type_index++];
|
const std::type_info *t = types[type_index++];
|
||||||
if (!t)
|
if (!t)
|
||||||
@ -395,7 +405,7 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_index != args || types[type_index] != nullptr)
|
if (arg_index != args - rec->has_args - rec->has_kwargs || types[type_index] != nullptr)
|
||||||
pybind11_fail("Internal error while parsing type signature (2)");
|
pybind11_fail("Internal error while parsing type signature (2)");
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION < 3
|
#if PY_MAJOR_VERSION < 3
|
||||||
@ -631,7 +641,7 @@ protected:
|
|||||||
named positional arguments weren't *also* specified via kwarg.
|
named positional arguments weren't *also* specified via kwarg.
|
||||||
2. If we weren't given enough, try to make up the omitted ones by checking
|
2. If we weren't given enough, try to make up the omitted ones by checking
|
||||||
whether they were provided by a kwarg matching the `py::arg("name")` name. If
|
whether they were provided by a kwarg matching the `py::arg("name")` name. If
|
||||||
so, use it (and remove it from kwargs; if not, see if the function binding
|
so, use it (and remove it from kwargs); if not, see if the function binding
|
||||||
provided a default that we can use.
|
provided a default that we can use.
|
||||||
3. Ensure that either all keyword arguments were "consumed", or that the function
|
3. Ensure that either all keyword arguments were "consumed", or that the function
|
||||||
takes a kwargs argument to accept unconsumed kwargs.
|
takes a kwargs argument to accept unconsumed kwargs.
|
||||||
@ -649,7 +659,7 @@ protected:
|
|||||||
size_t num_args = func.nargs; // Number of positional arguments that we need
|
size_t num_args = func.nargs; // Number of positional arguments that we need
|
||||||
if (func.has_args) --num_args; // (but don't count py::args
|
if (func.has_args) --num_args; // (but don't count py::args
|
||||||
if (func.has_kwargs) --num_args; // or py::kwargs)
|
if (func.has_kwargs) --num_args; // or py::kwargs)
|
||||||
size_t pos_args = num_args - func.nargs_kw_only;
|
size_t pos_args = func.nargs_pos;
|
||||||
|
|
||||||
if (!func.has_args && n_args_in > pos_args)
|
if (!func.has_args && n_args_in > pos_args)
|
||||||
continue; // Too many positional arguments for this overload
|
continue; // Too many positional arguments for this overload
|
||||||
@ -695,6 +705,10 @@ protected:
|
|||||||
if (bad_arg)
|
if (bad_arg)
|
||||||
continue; // Maybe it was meant for another overload (issue #688)
|
continue; // Maybe it was meant for another overload (issue #688)
|
||||||
|
|
||||||
|
// Keep track of how many position args we copied out in case we need to come back
|
||||||
|
// to copy the rest into a py::args argument.
|
||||||
|
size_t positional_args_copied = args_copied;
|
||||||
|
|
||||||
// We'll need to copy this if we steal some kwargs for defaults
|
// We'll need to copy this if we steal some kwargs for defaults
|
||||||
dict kwargs = reinterpret_borrow<dict>(kwargs_in);
|
dict kwargs = reinterpret_borrow<dict>(kwargs_in);
|
||||||
|
|
||||||
@ -747,6 +761,10 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
|
// If we're at the py::args index then first insert a stub for it to be replaced later
|
||||||
|
if (func.has_args && call.args.size() == func.nargs_pos)
|
||||||
|
call.args.push_back(none());
|
||||||
|
|
||||||
call.args.push_back(value);
|
call.args.push_back(value);
|
||||||
call.args_convert.push_back(arg_rec.convert);
|
call.args_convert.push_back(arg_rec.convert);
|
||||||
}
|
}
|
||||||
@ -769,16 +787,19 @@ protected:
|
|||||||
// We didn't copy out any position arguments from the args_in tuple, so we
|
// We didn't copy out any position arguments from the args_in tuple, so we
|
||||||
// can reuse it directly without copying:
|
// can reuse it directly without copying:
|
||||||
extra_args = reinterpret_borrow<tuple>(args_in);
|
extra_args = reinterpret_borrow<tuple>(args_in);
|
||||||
} else if (args_copied >= n_args_in) {
|
} else if (positional_args_copied >= n_args_in) {
|
||||||
extra_args = tuple(0);
|
extra_args = tuple(0);
|
||||||
} else {
|
} else {
|
||||||
size_t args_size = n_args_in - args_copied;
|
size_t args_size = n_args_in - positional_args_copied;
|
||||||
extra_args = tuple(args_size);
|
extra_args = tuple(args_size);
|
||||||
for (size_t i = 0; i < args_size; ++i) {
|
for (size_t i = 0; i < args_size; ++i) {
|
||||||
extra_args[i] = PyTuple_GET_ITEM(args_in, args_copied + i);
|
extra_args[i] = PyTuple_GET_ITEM(args_in, positional_args_copied + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
call.args.push_back(extra_args);
|
if (call.args.size() <= func.nargs_pos)
|
||||||
|
call.args.push_back(extra_args);
|
||||||
|
else
|
||||||
|
call.args[func.nargs_pos] = extra_args;
|
||||||
call.args_convert.push_back(false);
|
call.args_convert.push_back(false);
|
||||||
call.args_ref = std::move(extra_args);
|
call.args_ref = std::move(extra_args);
|
||||||
}
|
}
|
||||||
@ -1958,6 +1979,16 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
|
|||||||
// gets destroyed:
|
// gets destroyed:
|
||||||
weakref((PyObject *) type, cpp_function([type](handle wr) {
|
weakref((PyObject *) type, cpp_function([type](handle wr) {
|
||||||
get_internals().registered_types_py.erase(type);
|
get_internals().registered_types_py.erase(type);
|
||||||
|
|
||||||
|
// TODO consolidate the erasure code in pybind11_meta_dealloc() in class.h
|
||||||
|
auto &cache = get_internals().inactive_override_cache;
|
||||||
|
for (auto it = cache.begin(), last = cache.end(); it != last; ) {
|
||||||
|
if (it->first == reinterpret_cast<PyObject *>(type))
|
||||||
|
it = cache.erase(it);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
wr.dec_ref();
|
wr.dec_ref();
|
||||||
})).release();
|
})).release();
|
||||||
}
|
}
|
||||||
@ -2334,8 +2365,9 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty
|
|||||||
|
|
||||||
/* Don't call dispatch code if invoked from overridden function.
|
/* Don't call dispatch code if invoked from overridden function.
|
||||||
Unfortunately this doesn't work on PyPy. */
|
Unfortunately this doesn't work on PyPy. */
|
||||||
#if !defined(PYPY_VERSION)
|
#if !defined(PYPY_VERSION) && PY_VERSION_HEX < 0x030B0000
|
||||||
|
// TODO: Remove PyPy workaround for Python 3.11.
|
||||||
|
// Current API fails on 3.11 since co_varnames can be null.
|
||||||
#if PY_VERSION_HEX >= 0x03090000
|
#if PY_VERSION_HEX >= 0x03090000
|
||||||
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
|
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
|
||||||
if (frame != nullptr) {
|
if (frame != nullptr) {
|
||||||
@ -2343,7 +2375,7 @@ inline function get_type_override(const void *this_ptr, const type_info *this_ty
|
|||||||
// f_code is guaranteed to not be NULL
|
// f_code is guaranteed to not be NULL
|
||||||
if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) {
|
if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) {
|
||||||
PyObject* locals = PyEval_GetLocals();
|
PyObject* locals = PyEval_GetLocals();
|
||||||
if (locals != nullptr) {
|
if (locals != nullptr && f_code->co_varnames != nullptr) {
|
||||||
PyObject *self_caller = dict_getitem(
|
PyObject *self_caller = dict_getitem(
|
||||||
locals, PyTuple_GET_ITEM(f_code->co_varnames, 0)
|
locals, PyTuple_GET_ITEM(f_code->co_varnames, 0)
|
||||||
);
|
);
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
# include <optional>
|
# include <optional>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||||
|
# include <string_view>
|
||||||
|
#endif
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
|
|
||||||
/* A few forward declarations */
|
/* A few forward declarations */
|
||||||
@ -287,10 +291,10 @@ protected:
|
|||||||
struct borrowed_t { };
|
struct borrowed_t { };
|
||||||
struct stolen_t { };
|
struct stolen_t { };
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS // Issue in breathe 4.26.1
|
/// @cond BROKEN
|
||||||
template <typename T> friend T reinterpret_borrow(handle);
|
template <typename T> friend T reinterpret_borrow(handle);
|
||||||
template <typename T> friend T reinterpret_steal(handle);
|
template <typename T> friend T reinterpret_steal(handle);
|
||||||
#endif
|
/// @endcond
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Only accessible from derived classes and the reinterpret_* functions
|
// Only accessible from derived classes and the reinterpret_* functions
|
||||||
@ -431,7 +435,7 @@ inline void raise_from(error_already_set& err, PyObject *type, const char *messa
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** \defgroup python_builtins _
|
/** \defgroup python_builtins const_name
|
||||||
Unless stated otherwise, the following C++ functions behave the same
|
Unless stated otherwise, the following C++ functions behave the same
|
||||||
as their Python counterparts.
|
as their Python counterparts.
|
||||||
*/
|
*/
|
||||||
@ -1085,6 +1089,20 @@ public:
|
|||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
str(const std::string &s) : str(s.data(), s.size()) { }
|
str(const std::string &s) : str(s.data(), s.size()) { }
|
||||||
|
|
||||||
|
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||||
|
// enable_if is needed to avoid "ambiguous conversion" errors (see PR #3521).
|
||||||
|
template <typename T, detail::enable_if_t<std::is_same<T, std::string_view>::value, int> = 0>
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
str(T s) : str(s.data(), s.size()) { }
|
||||||
|
|
||||||
|
# ifdef PYBIND11_HAS_U8STRING
|
||||||
|
// reinterpret_cast here is safe (C++20 guarantees char8_t has the same size/alignment as char)
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
str(std::u8string_view s) : str(reinterpret_cast<const char*>(s.data()), s.size()) { }
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
explicit str(const bytes &b);
|
explicit str(const bytes &b);
|
||||||
|
|
||||||
/** \rst
|
/** \rst
|
||||||
@ -1167,6 +1185,26 @@ public:
|
|||||||
pybind11_fail("Unable to extract bytes contents!");
|
pybind11_fail("Unable to extract bytes contents!");
|
||||||
return std::string(buffer, (size_t) length);
|
return std::string(buffer, (size_t) length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||||
|
// enable_if is needed to avoid "ambiguous conversion" errors (see PR #3521).
|
||||||
|
template <typename T, detail::enable_if_t<std::is_same<T, std::string_view>::value, int> = 0>
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
bytes(T s) : bytes(s.data(), s.size()) { }
|
||||||
|
|
||||||
|
// Obtain a string view that views the current `bytes` buffer value. Note that this is only
|
||||||
|
// valid so long as the `bytes` instance remains alive and so generally should not outlive the
|
||||||
|
// lifetime of the `bytes` instance.
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator std::string_view() const {
|
||||||
|
char *buffer = nullptr;
|
||||||
|
ssize_t length = 0;
|
||||||
|
if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length))
|
||||||
|
pybind11_fail("Unable to extract bytes contents!");
|
||||||
|
return {buffer, static_cast<size_t>(length)};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
// Note: breathe >= 4.17.0 will fail to build docs if the below two constructors
|
// Note: breathe >= 4.17.0 will fail to build docs if the below two constructors
|
||||||
// are included in the doxygen group; close here and reopen after as a workaround
|
// are included in the doxygen group; close here and reopen after as a workaround
|
||||||
@ -1714,10 +1752,17 @@ public:
|
|||||||
static memoryview from_memory(const void *mem, ssize_t size) {
|
static memoryview from_memory(const void *mem, ssize_t size) {
|
||||||
return memoryview::from_memory(const_cast<void*>(mem), size, true);
|
return memoryview::from_memory(const_cast<void*>(mem), size, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||||
|
static memoryview from_memory(std::string_view mem) {
|
||||||
|
return from_memory(const_cast<char*>(mem.data()), static_cast<ssize_t>(mem.size()), true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
/// @cond DUPLICATE
|
||||||
inline memoryview memoryview::from_buffer(
|
inline memoryview memoryview::from_buffer(
|
||||||
void *ptr, ssize_t itemsize, const char* format,
|
void *ptr, ssize_t itemsize, const char* format,
|
||||||
detail::any_container<ssize_t> shape,
|
detail::any_container<ssize_t> shape,
|
||||||
@ -1745,7 +1790,7 @@ inline memoryview memoryview::from_buffer(
|
|||||||
throw error_already_set();
|
throw error_already_set();
|
||||||
return memoryview(object(obj, stolen_t{}));
|
return memoryview(object(obj, stolen_t{}));
|
||||||
}
|
}
|
||||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
/// @endcond
|
||||||
/// @} pytypes
|
/// @} pytypes
|
||||||
|
|
||||||
/// \addtogroup python_builtins
|
/// \addtogroup python_builtins
|
||||||
|
@ -78,7 +78,7 @@ template <typename Type, typename Key> struct set_caster {
|
|||||||
return s.release();
|
return s.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]"));
|
PYBIND11_TYPE_CASTER(type, const_name("Set[") + key_conv::name + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type, typename Key, typename Value> struct map_caster {
|
template <typename Type, typename Key, typename Value> struct map_caster {
|
||||||
@ -120,7 +120,7 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
|||||||
return d.release();
|
return d.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]"));
|
PYBIND11_TYPE_CASTER(Type, const_name("Dict[") + key_conv::name + const_name(", ") + value_conv::name + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type, typename Value> struct list_caster {
|
template <typename Type, typename Value> struct list_caster {
|
||||||
@ -166,7 +166,7 @@ public:
|
|||||||
return l.release();
|
return l.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));
|
PYBIND11_TYPE_CASTER(Type, const_name("List[") + value_conv::name + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
|
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
|
||||||
@ -223,7 +223,7 @@ public:
|
|||||||
return l.release();
|
return l.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]"));
|
PYBIND11_TYPE_CASTER(ArrayType, const_name("List[") + value_conv::name + const_name<Resizable>(const_name(""), const_name("[") + const_name<Size>() + const_name("]")) + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
|
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
|
||||||
@ -273,7 +273,7 @@ template<typename Type, typename Value = typename Type::value_type> struct optio
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(Type, _("Optional[") + value_conv::name + _("]"));
|
PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(PYBIND11_HAS_OPTIONAL)
|
#if defined(PYBIND11_HAS_OPTIONAL)
|
||||||
@ -353,7 +353,7 @@ struct variant_caster<V<Ts...>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using Type = V<Ts...>;
|
using Type = V<Ts...>;
|
||||||
PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name...) + _("]"));
|
PYBIND11_TYPE_CASTER(Type, const_name("Union[") + detail::concat(make_caster<Ts>::name...) + const_name("]"));
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(PYBIND11_HAS_VARIANT)
|
#if defined(PYBIND11_HAS_VARIANT)
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_TYPE_CASTER(T, _("os.PathLike"));
|
PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct type_caster<std::filesystem::path>
|
template<> struct type_caster<std::filesystem::path>
|
||||||
|
12
noxfile.py
12
noxfile.py
@ -57,10 +57,10 @@ def docs(session: nox.Session) -> None:
|
|||||||
session.chdir("docs")
|
session.chdir("docs")
|
||||||
|
|
||||||
if "pdf" in session.posargs:
|
if "pdf" in session.posargs:
|
||||||
session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
|
session.run("sphinx-build", "-b", "latexpdf", ".", "_build")
|
||||||
return
|
return
|
||||||
|
|
||||||
session.run("sphinx-build", "-M", "html", ".", "_build")
|
session.run("sphinx-build", "-b", "html", ".", "_build")
|
||||||
|
|
||||||
if "serve" in session.posargs:
|
if "serve" in session.posargs:
|
||||||
session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit")
|
session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit")
|
||||||
@ -85,5 +85,9 @@ def build(session: nox.Session) -> None:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
session.install("build")
|
session.install("build")
|
||||||
session.run("python", "-m", "build")
|
session.log("Building normal files")
|
||||||
session.run("python", "-m", "build", env={"PYBIND11_GLOBAL_SDIST": "1"})
|
session.run("python", "-m", "build", *session.posargs)
|
||||||
|
session.log("Building pybind11-global files (PYBIND11_GLOBAL_SDIST=1)")
|
||||||
|
session.run(
|
||||||
|
"python", "-m", "build", *session.posargs, env={"PYBIND11_GLOBAL_SDIST": "1"}
|
||||||
|
)
|
||||||
|
@ -8,5 +8,5 @@ def _to_int(s):
|
|||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
__version__ = "2.8.1"
|
__version__ = "2.9.0"
|
||||||
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||||
|
@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
@ -143,7 +144,12 @@ class Pybind11Extension(_Extension):
|
|||||||
if WIN:
|
if WIN:
|
||||||
cflags += ["/EHsc", "/bigobj"]
|
cflags += ["/EHsc", "/bigobj"]
|
||||||
else:
|
else:
|
||||||
cflags += ["-fvisibility=hidden", "-g0"]
|
cflags += ["-fvisibility=hidden"]
|
||||||
|
env_cflags = os.environ.get("CFLAGS", "")
|
||||||
|
env_cppflags = os.environ.get("CPPFLAGS", "")
|
||||||
|
c_cpp_flags = shlex.split(env_cflags) + shlex.split(env_cppflags)
|
||||||
|
if not any(opt.startswith("-g") for opt in c_cpp_flags):
|
||||||
|
cflags += ["-g0"]
|
||||||
if MACOS:
|
if MACOS:
|
||||||
cflags += ["-stdlib=libc++"]
|
cflags += ["-stdlib=libc++"]
|
||||||
ldflags += ["-stdlib=libc++"]
|
ldflags += ["-stdlib=libc++"]
|
||||||
@ -460,8 +466,14 @@ class ParallelCompile(object):
|
|||||||
threads = 1
|
threads = 1
|
||||||
|
|
||||||
if threads > 1:
|
if threads > 1:
|
||||||
for _ in ThreadPool(threads).imap_unordered(_single_compile, objects):
|
pool = ThreadPool(threads)
|
||||||
pass
|
# In Python 2, ThreadPool can't be used as a context manager.
|
||||||
|
# Once we are no longer supporting it, this can be 'with pool:'
|
||||||
|
try:
|
||||||
|
for _ in pool.imap_unordered(_single_compile, objects):
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
pool.terminate()
|
||||||
else:
|
else:
|
||||||
for ob in objects:
|
for ob in objects:
|
||||||
_single_compile(ob)
|
_single_compile(ob)
|
||||||
|
@ -429,6 +429,14 @@ foreach(target ${test_targets})
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
# Provide nice organisation in IDEs
|
||||||
|
if(NOT CMAKE_VERSION VERSION_LESS 3.8)
|
||||||
|
source_group(
|
||||||
|
TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
||||||
|
PREFIX "Header Files"
|
||||||
|
FILES ${PYBIND11_HEADERS})
|
||||||
|
endif()
|
||||||
|
|
||||||
# Make sure pytest is found or produce a warning
|
# Make sure pytest is found or produce a warning
|
||||||
pybind11_find_import(pytest VERSION 3.1)
|
pybind11_find_import(pytest VERSION 3.1)
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import pytest
|
|||||||
|
|
||||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
|
MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
|
||||||
|
WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("parallel", [False, True])
|
@pytest.mark.parametrize("parallel", [False, True])
|
||||||
@ -71,13 +72,20 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
|||||||
encoding="ascii",
|
encoding="ascii",
|
||||||
)
|
)
|
||||||
|
|
||||||
subprocess.check_call(
|
out = subprocess.check_output(
|
||||||
[sys.executable, "setup.py", "build_ext", "--inplace"],
|
[sys.executable, "setup.py", "build_ext", "--inplace"],
|
||||||
stdout=sys.stdout,
|
|
||||||
stderr=sys.stderr,
|
|
||||||
)
|
)
|
||||||
|
if not WIN:
|
||||||
|
assert b"-g0" in out
|
||||||
|
out = subprocess.check_output(
|
||||||
|
[sys.executable, "setup.py", "build_ext", "--inplace", "--force"],
|
||||||
|
env=dict(os.environ, CFLAGS="-g"),
|
||||||
|
)
|
||||||
|
if not WIN:
|
||||||
|
assert b"-g0" not in out
|
||||||
|
|
||||||
# Debug helper printout, normally hidden
|
# Debug helper printout, normally hidden
|
||||||
|
print(out)
|
||||||
for item in tmpdir.listdir():
|
for item in tmpdir.listdir():
|
||||||
print(item.basename)
|
print(item.basename)
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ PYBIND11_NAMESPACE_BEGIN(pybind11)
|
|||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
template<> class type_caster<RValueCaster> {
|
template<> class type_caster<RValueCaster> {
|
||||||
public:
|
public:
|
||||||
PYBIND11_TYPE_CASTER(RValueCaster, _("RValueCaster"));
|
PYBIND11_TYPE_CASTER(RValueCaster, const_name("RValueCaster"));
|
||||||
static handle cast(RValueCaster &&, return_value_policy, handle) { return py::str("rvalue").release(); }
|
static handle cast(RValueCaster &&, return_value_policy, handle) { return py::str("rvalue").release(); }
|
||||||
static handle cast(const RValueCaster &, return_value_policy, handle) { return py::str("lvalue").release(); }
|
static handle cast(const RValueCaster &, return_value_policy, handle) { return py::str("lvalue").release(); }
|
||||||
};
|
};
|
||||||
|
@ -2,7 +2,7 @@ numpy==1.16.6; python_version<"3.6" and sys_platform!="win32" and platform_pytho
|
|||||||
numpy==1.19.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.6"
|
numpy==1.19.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.6"
|
||||||
numpy==1.20.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
|
numpy==1.20.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
|
||||||
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
|
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
|
||||||
numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7"
|
numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.11"
|
||||||
py @ git+https://github.com/pytest-dev/py; python_version>="3.11"
|
py @ git+https://github.com/pytest-dev/py; python_version>="3.11"
|
||||||
pytest==4.6.9; python_version<"3.5"
|
pytest==4.6.9; python_version<"3.5"
|
||||||
pytest==6.1.2; python_version=="3.5"
|
pytest==6.1.2; python_version=="3.5"
|
||||||
|
@ -36,6 +36,10 @@ def test_from_python():
|
|||||||
|
|
||||||
|
|
||||||
# https://foss.heptapod.net/pypy/pypy/-/issues/2444
|
# https://foss.heptapod.net/pypy/pypy/-/issues/2444
|
||||||
|
# TODO: fix on recent PyPy
|
||||||
|
@pytest.mark.xfail(
|
||||||
|
env.PYPY, reason="PyPy 7.3.7 doesn't clear this anymore", strict=False
|
||||||
|
)
|
||||||
def test_to_python():
|
def test_to_python():
|
||||||
mat = m.Matrix(5, 4)
|
mat = m.Matrix(5, 4)
|
||||||
assert memoryview(mat).shape == (5, 4)
|
assert memoryview(mat).shape == (5, 4)
|
||||||
|
@ -19,7 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
|||||||
template <>
|
template <>
|
||||||
class type_caster<ConstRefCasted> {
|
class type_caster<ConstRefCasted> {
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = _<ConstRefCasted>();
|
static constexpr auto name = const_name<ConstRefCasted>();
|
||||||
|
|
||||||
// Input is unimportant, a new value will always be constructed based on the
|
// Input is unimportant, a new value will always be constructed based on the
|
||||||
// cast operator.
|
// cast operator.
|
||||||
@ -140,11 +140,35 @@ TEST_SUBMODULE(builtin_casters, m) {
|
|||||||
m.def("string_view16_return", []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
|
m.def("string_view16_return", []() { return std::u16string_view(u"utf16 secret \U0001f382"); });
|
||||||
m.def("string_view32_return", []() { return std::u32string_view(U"utf32 secret \U0001f382"); });
|
m.def("string_view32_return", []() { return std::u32string_view(U"utf32 secret \U0001f382"); });
|
||||||
|
|
||||||
|
// The inner lambdas here are to also test implicit conversion
|
||||||
|
using namespace std::literals;
|
||||||
|
m.def("string_view_bytes", []() { return [](py::bytes b) { return b; }("abc \x80\x80 def"sv); });
|
||||||
|
m.def("string_view_str", []() { return [](py::str s) { return s; }("abc \342\200\275 def"sv); });
|
||||||
|
m.def("string_view_from_bytes", [](const py::bytes &b) { return [](std::string_view s) { return s; }(b); });
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
m.def("string_view_memoryview", []() {
|
||||||
|
static constexpr auto val = "Have some \360\237\216\202"sv;
|
||||||
|
return py::memoryview::from_memory(val);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
|
|
||||||
# ifdef PYBIND11_HAS_U8STRING
|
# ifdef PYBIND11_HAS_U8STRING
|
||||||
m.def("string_view8_print", [](std::u8string_view s) { py::print(s, s.size()); });
|
m.def("string_view8_print", [](std::u8string_view s) { py::print(s, s.size()); });
|
||||||
m.def("string_view8_chars", [](std::u8string_view s) { py::list l; for (auto c : s) l.append((std::uint8_t) c); return l; });
|
m.def("string_view8_chars", [](std::u8string_view s) { py::list l; for (auto c : s) l.append((std::uint8_t) c); return l; });
|
||||||
m.def("string_view8_return", []() { return std::u8string_view(u8"utf8 secret \U0001f382"); });
|
m.def("string_view8_return", []() { return std::u8string_view(u8"utf8 secret \U0001f382"); });
|
||||||
|
m.def("string_view8_str", []() { return py::str{std::u8string_view{u8"abc ‽ def"}}; });
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
struct TypeWithBothOperatorStringAndStringView {
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator std::string() const { return "success"; }
|
||||||
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
|
operator std::string_view() const { return "failure"; }
|
||||||
|
};
|
||||||
|
m.def("bytes_from_type_with_both_operator_string_and_string_view",
|
||||||
|
[]() { return py::bytes(TypeWithBothOperatorStringAndStringView()); });
|
||||||
|
m.def("str_from_type_with_both_operator_string_and_string_view",
|
||||||
|
[]() { return py::str(TypeWithBothOperatorStringAndStringView()); });
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// test_integer_casting
|
// test_integer_casting
|
||||||
|
@ -206,6 +206,17 @@ def test_string_view(capture):
|
|||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
assert m.string_view_bytes() == b"abc \x80\x80 def"
|
||||||
|
assert m.string_view_str() == u"abc ‽ def"
|
||||||
|
assert m.string_view_from_bytes(u"abc ‽ def".encode("utf-8")) == u"abc ‽ def"
|
||||||
|
if hasattr(m, "has_u8string"):
|
||||||
|
assert m.string_view8_str() == u"abc ‽ def"
|
||||||
|
if not env.PY2:
|
||||||
|
assert m.string_view_memoryview() == "Have some 🎂".encode()
|
||||||
|
|
||||||
|
assert m.bytes_from_type_with_both_operator_string_and_string_view() == b"success"
|
||||||
|
assert m.str_from_type_with_both_operator_string_and_string_view() == "success"
|
||||||
|
|
||||||
|
|
||||||
def test_integer_casting():
|
def test_integer_casting():
|
||||||
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
|
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
|
||||||
@ -299,7 +310,8 @@ def test_int_convert():
|
|||||||
assert noconvert(7) == 7
|
assert noconvert(7) == 7
|
||||||
cant_convert(3.14159)
|
cant_convert(3.14159)
|
||||||
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
|
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
|
||||||
if (3, 8) <= env.PY < (3, 10):
|
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
|
||||||
|
if (3, 8) <= env.PY < (3, 10) and env.CPYTHON:
|
||||||
with env.deprecated_call():
|
with env.deprecated_call():
|
||||||
assert convert(Int()) == 42
|
assert convert(Int()) == 42
|
||||||
else:
|
else:
|
||||||
@ -334,7 +346,9 @@ def test_numpy_int_convert():
|
|||||||
|
|
||||||
# The implicit conversion from np.float32 is undesirable but currently accepted.
|
# The implicit conversion from np.float32 is undesirable but currently accepted.
|
||||||
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
|
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
|
||||||
if (3, 8) <= env.PY < (3, 10):
|
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
|
||||||
|
# https://github.com/pybind/pybind11/issues/3408
|
||||||
|
if (3, 8) <= env.PY < (3, 10) and env.CPYTHON:
|
||||||
with env.deprecated_call():
|
with env.deprecated_call():
|
||||||
assert convert(np.float32(3.14159)) == 3
|
assert convert(np.float32(3.14159)) == 3
|
||||||
else:
|
else:
|
||||||
|
@ -85,13 +85,13 @@ public:
|
|||||||
PYBIND11_NAMESPACE_BEGIN(pybind11)
|
PYBIND11_NAMESPACE_BEGIN(pybind11)
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
template <> struct type_caster<MoveOnlyInt> {
|
template <> struct type_caster<MoveOnlyInt> {
|
||||||
PYBIND11_TYPE_CASTER(MoveOnlyInt, _("MoveOnlyInt"));
|
PYBIND11_TYPE_CASTER(MoveOnlyInt, const_name("MoveOnlyInt"));
|
||||||
bool load(handle src, bool) { value = MoveOnlyInt(src.cast<int>()); return true; }
|
bool load(handle src, bool) { value = MoveOnlyInt(src.cast<int>()); return true; }
|
||||||
static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct type_caster<MoveOrCopyInt> {
|
template <> struct type_caster<MoveOrCopyInt> {
|
||||||
PYBIND11_TYPE_CASTER(MoveOrCopyInt, _("MoveOrCopyInt"));
|
PYBIND11_TYPE_CASTER(MoveOrCopyInt, const_name("MoveOrCopyInt"));
|
||||||
bool load(handle src, bool) { value = MoveOrCopyInt(src.cast<int>()); return true; }
|
bool load(handle src, bool) { value = MoveOrCopyInt(src.cast<int>()); return true; }
|
||||||
static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
static handle cast(const MoveOrCopyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
||||||
};
|
};
|
||||||
@ -100,7 +100,7 @@ template <> struct type_caster<CopyOnlyInt> {
|
|||||||
protected:
|
protected:
|
||||||
CopyOnlyInt value;
|
CopyOnlyInt value;
|
||||||
public:
|
public:
|
||||||
static constexpr auto name = _("CopyOnlyInt");
|
static constexpr auto name = const_name("CopyOnlyInt");
|
||||||
bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; }
|
bool load(handle src, bool) { value = CopyOnlyInt(src.cast<int>()); return true; }
|
||||||
static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
static handle cast(const CopyOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
||||||
static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {
|
static handle cast(const CopyOnlyInt *src, return_value_policy policy, handle parent) {
|
||||||
|
@ -18,7 +18,12 @@ class ArgAlwaysConverts { };
|
|||||||
namespace pybind11 { namespace detail {
|
namespace pybind11 { namespace detail {
|
||||||
template <> struct type_caster<ArgInspector1> {
|
template <> struct type_caster<ArgInspector1> {
|
||||||
public:
|
public:
|
||||||
|
// Classic
|
||||||
|
#ifndef _
|
||||||
PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
|
PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
|
||||||
|
#else
|
||||||
|
PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));
|
||||||
|
#endif
|
||||||
|
|
||||||
bool load(handle src, bool convert) {
|
bool load(handle src, bool convert) {
|
||||||
value.arg = "loading ArgInspector1 argument " +
|
value.arg = "loading ArgInspector1 argument " +
|
||||||
@ -33,7 +38,7 @@ public:
|
|||||||
};
|
};
|
||||||
template <> struct type_caster<ArgInspector2> {
|
template <> struct type_caster<ArgInspector2> {
|
||||||
public:
|
public:
|
||||||
PYBIND11_TYPE_CASTER(ArgInspector2, _("ArgInspector2"));
|
PYBIND11_TYPE_CASTER(ArgInspector2, const_name("ArgInspector2"));
|
||||||
|
|
||||||
bool load(handle src, bool convert) {
|
bool load(handle src, bool convert) {
|
||||||
value.arg = "loading ArgInspector2 argument " +
|
value.arg = "loading ArgInspector2 argument " +
|
||||||
@ -48,7 +53,7 @@ public:
|
|||||||
};
|
};
|
||||||
template <> struct type_caster<ArgAlwaysConverts> {
|
template <> struct type_caster<ArgAlwaysConverts> {
|
||||||
public:
|
public:
|
||||||
PYBIND11_TYPE_CASTER(ArgAlwaysConverts, _("ArgAlwaysConverts"));
|
PYBIND11_TYPE_CASTER(ArgAlwaysConverts, const_name("ArgAlwaysConverts"));
|
||||||
|
|
||||||
bool load(handle, bool convert) {
|
bool load(handle, bool convert) {
|
||||||
return convert;
|
return convert;
|
||||||
@ -76,7 +81,7 @@ public:
|
|||||||
};
|
};
|
||||||
namespace pybind11 { namespace detail {
|
namespace pybind11 { namespace detail {
|
||||||
template <> struct type_caster<DestructionTester> {
|
template <> struct type_caster<DestructionTester> {
|
||||||
PYBIND11_TYPE_CASTER(DestructionTester, _("DestructionTester"));
|
PYBIND11_TYPE_CASTER(DestructionTester, const_name("DestructionTester"));
|
||||||
bool load(handle, bool) { return true; }
|
bool load(handle, bool) { return true; }
|
||||||
|
|
||||||
static handle cast(const DestructionTester &, return_value_policy, handle) {
|
static handle cast(const DestructionTester &, return_value_policy, handle) {
|
||||||
|
@ -25,7 +25,7 @@ pybind11_enable_warnings(test_embed)
|
|||||||
target_link_libraries(test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads)
|
target_link_libraries(test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads)
|
||||||
|
|
||||||
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||||
file(COPY test_interpreter.py DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
file(COPY test_interpreter.py test_trampoline.py DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_target(
|
add_custom_target(
|
||||||
|
@ -37,6 +37,22 @@ class PyWidget final : public Widget {
|
|||||||
std::string argv0() const override { PYBIND11_OVERRIDE_PURE(std::string, Widget, argv0); }
|
std::string argv0() const override { PYBIND11_OVERRIDE_PURE(std::string, Widget, argv0); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class test_override_cache_helper {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual int func() { return 0; }
|
||||||
|
|
||||||
|
test_override_cache_helper() = default;
|
||||||
|
virtual ~test_override_cache_helper() = default;
|
||||||
|
// Non-copyable
|
||||||
|
test_override_cache_helper &operator=(test_override_cache_helper const &Right) = delete;
|
||||||
|
test_override_cache_helper(test_override_cache_helper const &Copy) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
class test_override_cache_helper_trampoline : public test_override_cache_helper {
|
||||||
|
int func() override { PYBIND11_OVERRIDE(int, test_override_cache_helper, func); }
|
||||||
|
};
|
||||||
|
|
||||||
PYBIND11_EMBEDDED_MODULE(widget_module, m) {
|
PYBIND11_EMBEDDED_MODULE(widget_module, m) {
|
||||||
py::class_<Widget, PyWidget>(m, "Widget")
|
py::class_<Widget, PyWidget>(m, "Widget")
|
||||||
.def(py::init<std::string>())
|
.def(py::init<std::string>())
|
||||||
@ -45,6 +61,12 @@ PYBIND11_EMBEDDED_MODULE(widget_module, m) {
|
|||||||
m.def("add", [](int i, int j) { return i + j; });
|
m.def("add", [](int i, int j) { return i + j; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PYBIND11_EMBEDDED_MODULE(trampoline_module, m) {
|
||||||
|
py::class_<test_override_cache_helper, test_override_cache_helper_trampoline, std::shared_ptr<test_override_cache_helper>>(m, "test_override_cache_helper")
|
||||||
|
.def(py::init_alias<>())
|
||||||
|
.def("func", &test_override_cache_helper::func);
|
||||||
|
}
|
||||||
|
|
||||||
PYBIND11_EMBEDDED_MODULE(throw_exception, ) {
|
PYBIND11_EMBEDDED_MODULE(throw_exception, ) {
|
||||||
throw std::runtime_error("C++ Error");
|
throw std::runtime_error("C++ Error");
|
||||||
}
|
}
|
||||||
@ -73,6 +95,33 @@ TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
|
|||||||
REQUIRE(cpp_widget.the_answer() == 42);
|
REQUIRE(cpp_widget.the_answer() == 42);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Override cache") {
|
||||||
|
auto module_ = py::module_::import("test_trampoline");
|
||||||
|
REQUIRE(py::hasattr(module_, "func"));
|
||||||
|
REQUIRE(py::hasattr(module_, "func2"));
|
||||||
|
|
||||||
|
auto locals = py::dict(**module_.attr("__dict__"));
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < 1500; ++i) {
|
||||||
|
std::shared_ptr<test_override_cache_helper> p_obj;
|
||||||
|
std::shared_ptr<test_override_cache_helper> p_obj2;
|
||||||
|
|
||||||
|
py::object loc_inst = locals["func"]();
|
||||||
|
p_obj = py::cast<std::shared_ptr<test_override_cache_helper>>(loc_inst);
|
||||||
|
|
||||||
|
int ret = p_obj->func();
|
||||||
|
|
||||||
|
REQUIRE(ret == 42);
|
||||||
|
|
||||||
|
loc_inst = locals["func2"]();
|
||||||
|
|
||||||
|
p_obj2 = py::cast<std::shared_ptr<test_override_cache_helper>>(loc_inst);
|
||||||
|
|
||||||
|
p_obj2->func();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST_CASE("Import error handling") {
|
TEST_CASE("Import error handling") {
|
||||||
REQUIRE_NOTHROW(py::module_::import("widget_module"));
|
REQUIRE_NOTHROW(py::module_::import("widget_module"));
|
||||||
REQUIRE_THROWS_WITH(py::module_::import("throw_exception"),
|
REQUIRE_THROWS_WITH(py::module_::import("throw_exception"),
|
||||||
|
18
tests/test_embed/test_trampoline.py
Normal file
18
tests/test_embed/test_trampoline.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import trampoline_module
|
||||||
|
|
||||||
|
|
||||||
|
def func():
|
||||||
|
class Test(trampoline_module.test_override_cache_helper):
|
||||||
|
def func(self):
|
||||||
|
return 42
|
||||||
|
|
||||||
|
return Test()
|
||||||
|
|
||||||
|
|
||||||
|
def func2():
|
||||||
|
class Test(trampoline_module.test_override_cache_helper):
|
||||||
|
pass
|
||||||
|
|
||||||
|
return Test()
|
@ -3,7 +3,7 @@ import sys
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
import env # noqa: F401
|
import env
|
||||||
import pybind11_cross_module_tests as cm
|
import pybind11_cross_module_tests as cm
|
||||||
from pybind11_tests import exceptions as m
|
from pybind11_tests import exceptions as m
|
||||||
|
|
||||||
@ -97,6 +97,8 @@ def ignore_pytest_unraisable_warning(f):
|
|||||||
return f
|
return f
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583
|
||||||
|
@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
|
||||||
@ignore_pytest_unraisable_warning
|
@ignore_pytest_unraisable_warning
|
||||||
def test_python_alreadyset_in_destructor(monkeypatch, capsys):
|
def test_python_alreadyset_in_destructor(monkeypatch, capsys):
|
||||||
hooked = False
|
hooked = False
|
||||||
|
@ -56,6 +56,23 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
|||||||
m.def("mixed_plus_args_kwargs_defaults", mixed_plus_both,
|
m.def("mixed_plus_args_kwargs_defaults", mixed_plus_both,
|
||||||
py::arg("i") = 1, py::arg("j") = 3.14159);
|
py::arg("i") = 1, py::arg("j") = 3.14159);
|
||||||
|
|
||||||
|
m.def("args_kwonly",
|
||||||
|
[](int i, double j, const py::args &args, int z) { return py::make_tuple(i, j, args, z); },
|
||||||
|
"i"_a, "j"_a, "z"_a);
|
||||||
|
m.def("args_kwonly_kwargs",
|
||||||
|
[](int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
|
||||||
|
return py::make_tuple(i, j, args, z, kwargs); },
|
||||||
|
"i"_a, "j"_a, py::kw_only{}, "z"_a);
|
||||||
|
m.def("args_kwonly_kwargs_defaults",
|
||||||
|
[](int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
|
||||||
|
return py::make_tuple(i, j, args, z, kwargs); },
|
||||||
|
"i"_a = 1, "j"_a = 3.14159, "z"_a = 42);
|
||||||
|
m.def("args_kwonly_full_monty",
|
||||||
|
[](int h, int i, double j, const py::args &args, int z, const py::kwargs &kwargs) {
|
||||||
|
return py::make_tuple(h, i, j, args, z, kwargs); },
|
||||||
|
py::arg() = 1, py::arg() = 2, py::pos_only{}, "j"_a = 3.14159, "z"_a = 42);
|
||||||
|
|
||||||
|
|
||||||
// test_args_refcount
|
// test_args_refcount
|
||||||
// PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
|
// PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
|
||||||
#ifdef PYPY_VERSION
|
#ifdef PYPY_VERSION
|
||||||
@ -150,4 +167,21 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
|||||||
"class_default_argument",
|
"class_default_argument",
|
||||||
[](py::object a) { return py::repr(std::move(a)); },
|
[](py::object a) { return py::repr(std::move(a)); },
|
||||||
"a"_a = py::module_::import("decimal").attr("Decimal"));
|
"a"_a = py::module_::import("decimal").attr("Decimal"));
|
||||||
|
|
||||||
|
// Initial implementation of kw_only was broken when used on a method/constructor before any
|
||||||
|
// other arguments
|
||||||
|
// https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
|
||||||
|
|
||||||
|
struct first_arg_kw_only {};
|
||||||
|
py::class_<first_arg_kw_only>(m, "first_arg_kw_only")
|
||||||
|
.def(py::init([](int) { return first_arg_kw_only(); }),
|
||||||
|
py::kw_only(), // This being before any args was broken
|
||||||
|
py::arg("i") = 0)
|
||||||
|
.def("method", [](first_arg_kw_only&, int, int) {},
|
||||||
|
py::kw_only(), // and likewise here
|
||||||
|
py::arg("i") = 1, py::arg("j") = 2)
|
||||||
|
// Closely related: pos_only marker didn't show up properly when it was before any other
|
||||||
|
// arguments (although that is fairly useless in practice).
|
||||||
|
.def("pos_only", [](first_arg_kw_only&, int, int) {},
|
||||||
|
py::pos_only{}, py::arg("i"), py::arg("j"));
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,53 @@ def test_mixed_args_and_kwargs(msg):
|
|||||||
""" # noqa: E501 line too long
|
""" # noqa: E501 line too long
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Arguments after a py::args are automatically keyword-only (pybind 2.9+)
|
||||||
|
assert m.args_kwonly(2, 2.5, z=22) == (2, 2.5, (), 22)
|
||||||
|
assert m.args_kwonly(2, 2.5, "a", "b", "c", z=22) == (2, 2.5, ("a", "b", "c"), 22)
|
||||||
|
assert m.args_kwonly(z=22, i=4, j=16) == (4, 16, (), 22)
|
||||||
|
|
||||||
|
with pytest.raises(TypeError) as excinfo:
|
||||||
|
assert m.args_kwonly(2, 2.5, 22) # missing z= keyword
|
||||||
|
assert (
|
||||||
|
msg(excinfo.value)
|
||||||
|
== """
|
||||||
|
args_kwonly(): incompatible function arguments. The following argument types are supported:
|
||||||
|
1. (i: int, j: float, *args, z: int) -> tuple
|
||||||
|
|
||||||
|
Invoked with: 2, 2.5, 22
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
assert m.args_kwonly_kwargs(i=1, k=4, j=10, z=-1, y=9) == (
|
||||||
|
1,
|
||||||
|
10,
|
||||||
|
(),
|
||||||
|
-1,
|
||||||
|
{"k": 4, "y": 9},
|
||||||
|
)
|
||||||
|
assert m.args_kwonly_kwargs(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, z=11, y=12) == (
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
(3, 4, 5, 6, 7, 8, 9, 10),
|
||||||
|
11,
|
||||||
|
{"y": 12},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
m.args_kwonly_kwargs.__doc__
|
||||||
|
== "args_kwonly_kwargs(i: int, j: float, *args, z: int, **kwargs) -> tuple\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert (
|
||||||
|
m.args_kwonly_kwargs_defaults.__doc__
|
||||||
|
== "args_kwonly_kwargs_defaults(i: int = 1, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple\n" # noqa: E501 line too long
|
||||||
|
)
|
||||||
|
assert m.args_kwonly_kwargs_defaults() == (1, 3.14159, (), 42, {})
|
||||||
|
assert m.args_kwonly_kwargs_defaults(2) == (2, 3.14159, (), 42, {})
|
||||||
|
assert m.args_kwonly_kwargs_defaults(z=-99) == (1, 3.14159, (), -99, {})
|
||||||
|
assert m.args_kwonly_kwargs_defaults(5, 6, 7, 8) == (5, 6, (7, 8), 42, {})
|
||||||
|
assert m.args_kwonly_kwargs_defaults(5, 6, 7, m=8) == (5, 6, (7,), 42, {"m": 8})
|
||||||
|
assert m.args_kwonly_kwargs_defaults(5, 6, 7, m=8, z=9) == (5, 6, (7,), 9, {"m": 8})
|
||||||
|
|
||||||
|
|
||||||
def test_keyword_only_args(msg):
|
def test_keyword_only_args(msg):
|
||||||
assert m.kw_only_all(i=1, j=2) == (1, 2)
|
assert m.kw_only_all(i=1, j=2) == (1, 2)
|
||||||
@ -178,10 +225,23 @@ def test_keyword_only_args(msg):
|
|||||||
assert (
|
assert (
|
||||||
msg(excinfo.value)
|
msg(excinfo.value)
|
||||||
== """
|
== """
|
||||||
arg(): cannot specify an unnamed argument after an kw_only() annotation
|
arg(): cannot specify an unnamed argument after a kw_only() annotation or args() argument
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
|
||||||
|
x = m.first_arg_kw_only(i=1)
|
||||||
|
x.method()
|
||||||
|
x.method(i=1, j=2)
|
||||||
|
assert (
|
||||||
|
m.first_arg_kw_only.__init__.__doc__
|
||||||
|
== "__init__(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 0) -> None\n" # noqa: E501 line too long
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
m.first_arg_kw_only.method.__doc__
|
||||||
|
== "method(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 1, j: int = 2) -> None\n" # noqa: E501 line too long
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_positional_only_args(msg):
|
def test_positional_only_args(msg):
|
||||||
assert m.pos_only_all(1, 2) == (1, 2)
|
assert m.pos_only_all(1, 2) == (1, 2)
|
||||||
@ -222,6 +282,55 @@ def test_positional_only_args(msg):
|
|||||||
m.pos_only_def_mix(1, j=4)
|
m.pos_only_def_mix(1, j=4)
|
||||||
assert "incompatible function arguments" in str(excinfo.value)
|
assert "incompatible function arguments" in str(excinfo.value)
|
||||||
|
|
||||||
|
# Mix it with args and kwargs:
|
||||||
|
assert (
|
||||||
|
m.args_kwonly_full_monty.__doc__
|
||||||
|
== "args_kwonly_full_monty(arg0: int = 1, arg1: int = 2, /, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple\n" # noqa: E501 line too long
|
||||||
|
)
|
||||||
|
assert m.args_kwonly_full_monty() == (1, 2, 3.14159, (), 42, {})
|
||||||
|
assert m.args_kwonly_full_monty(8) == (8, 2, 3.14159, (), 42, {})
|
||||||
|
assert m.args_kwonly_full_monty(8, 9) == (8, 9, 3.14159, (), 42, {})
|
||||||
|
assert m.args_kwonly_full_monty(8, 9, 10) == (8, 9, 10.0, (), 42, {})
|
||||||
|
assert m.args_kwonly_full_monty(3, 4, 5, 6, 7, m=8, z=9) == (
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5.0,
|
||||||
|
(
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
),
|
||||||
|
9,
|
||||||
|
{"m": 8},
|
||||||
|
)
|
||||||
|
assert m.args_kwonly_full_monty(3, 4, 5, 6, 7, m=8, z=9) == (
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5.0,
|
||||||
|
(
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
),
|
||||||
|
9,
|
||||||
|
{"m": 8},
|
||||||
|
)
|
||||||
|
assert m.args_kwonly_full_monty(5, j=7, m=8, z=9) == (5, 2, 7.0, (), 9, {"m": 8})
|
||||||
|
assert m.args_kwonly_full_monty(i=5, j=7, m=8, z=9) == (
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
7.0,
|
||||||
|
(),
|
||||||
|
9,
|
||||||
|
{"i": 5, "m": 8},
|
||||||
|
)
|
||||||
|
|
||||||
|
# pos_only at the beginning of the argument list was "broken" in how it was displayed (though
|
||||||
|
# this is fairly useless in practice). Related to:
|
||||||
|
# https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
|
||||||
|
assert (
|
||||||
|
m.first_arg_kw_only.pos_only.__doc__
|
||||||
|
== "pos_only(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, /, i: int, j: int) -> None\n" # noqa: E501 line too long
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_signatures():
|
def test_signatures():
|
||||||
assert "kw_only_all(*, i: int, j: int) -> tuple\n" == m.kw_only_all.__doc__
|
assert "kw_only_all(*, i: int, j: int) -> tuple\n" == m.kw_only_all.__doc__
|
||||||
|
@ -159,6 +159,14 @@ struct RefQualified {
|
|||||||
int constRefQualified(int other) const & { return value + other; }
|
int constRefQualified(int other) const & { return value + other; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Test rvalue ref param
|
||||||
|
struct RValueRefParam {
|
||||||
|
std::size_t func1(std::string&& s) { return s.size(); }
|
||||||
|
std::size_t func2(std::string&& s) const { return s.size(); }
|
||||||
|
std::size_t func3(std::string&& s) & { return s.size(); }
|
||||||
|
std::size_t func4(std::string&& s) const & { return s.size(); }
|
||||||
|
};
|
||||||
|
|
||||||
TEST_SUBMODULE(methods_and_attributes, m) {
|
TEST_SUBMODULE(methods_and_attributes, m) {
|
||||||
// test_methods_and_attributes
|
// test_methods_and_attributes
|
||||||
py::class_<ExampleMandA> emna(m, "ExampleMandA");
|
py::class_<ExampleMandA> emna(m, "ExampleMandA");
|
||||||
@ -409,4 +417,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
|
|||||||
.def_readonly("value", &RefQualified::value)
|
.def_readonly("value", &RefQualified::value)
|
||||||
.def("refQualified", &RefQualified::refQualified)
|
.def("refQualified", &RefQualified::refQualified)
|
||||||
.def("constRefQualified", &RefQualified::constRefQualified);
|
.def("constRefQualified", &RefQualified::constRefQualified);
|
||||||
|
|
||||||
|
py::class_<RValueRefParam>(m, "RValueRefParam")
|
||||||
|
.def(py::init<>())
|
||||||
|
.def("func1", &RValueRefParam::func1)
|
||||||
|
.def("func2", &RValueRefParam::func2)
|
||||||
|
.def("func3", &RValueRefParam::func3)
|
||||||
|
.def("func4", &RValueRefParam::func4);
|
||||||
}
|
}
|
||||||
|
@ -515,3 +515,11 @@ def test_overload_ordering():
|
|||||||
assert "2. (arg0: {}) -> int".format(uni_name) in str(err.value)
|
assert "2. (arg0: {}) -> int".format(uni_name) in str(err.value)
|
||||||
assert "3. (arg0: {}) -> int".format(uni_name) in str(err.value)
|
assert "3. (arg0: {}) -> int".format(uni_name) in str(err.value)
|
||||||
assert "4. (arg0: int) -> int" in str(err.value)
|
assert "4. (arg0: int) -> int" in str(err.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_rvalue_ref_param():
|
||||||
|
r = m.RValueRefParam()
|
||||||
|
assert r.func1("123") == 3
|
||||||
|
assert r.func2("1234") == 4
|
||||||
|
assert r.func3("12345") == 5
|
||||||
|
assert r.func4("123456") == 6
|
||||||
|
@ -214,6 +214,25 @@ static void test_gil_from_thread() {
|
|||||||
t.join();
|
t.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class test_override_cache_helper {
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual int func() { return 0; }
|
||||||
|
|
||||||
|
test_override_cache_helper() = default;
|
||||||
|
virtual ~test_override_cache_helper() = default;
|
||||||
|
// Non-copyable
|
||||||
|
test_override_cache_helper &operator=(test_override_cache_helper const &Right) = delete;
|
||||||
|
test_override_cache_helper(test_override_cache_helper const &Copy) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
class test_override_cache_helper_trampoline : public test_override_cache_helper {
|
||||||
|
int func() override { PYBIND11_OVERRIDE(int, test_override_cache_helper, func); }
|
||||||
|
};
|
||||||
|
|
||||||
|
inline int test_override_cache(std::shared_ptr<test_override_cache_helper> const &instance) { return instance->func(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
|
// Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
|
||||||
// rather long).
|
// rather long).
|
||||||
@ -378,6 +397,12 @@ TEST_SUBMODULE(virtual_functions, m) {
|
|||||||
// .def("str_ref", &OverrideTest::str_ref)
|
// .def("str_ref", &OverrideTest::str_ref)
|
||||||
.def("A_value", &OverrideTest::A_value)
|
.def("A_value", &OverrideTest::A_value)
|
||||||
.def("A_ref", &OverrideTest::A_ref);
|
.def("A_ref", &OverrideTest::A_ref);
|
||||||
|
|
||||||
|
py::class_<test_override_cache_helper, test_override_cache_helper_trampoline, std::shared_ptr<test_override_cache_helper>>(m, "test_override_cache_helper")
|
||||||
|
.def(py::init_alias<>())
|
||||||
|
.def("func", &test_override_cache_helper::func);
|
||||||
|
|
||||||
|
m.def("test_override_cache", test_override_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -439,3 +439,22 @@ def test_issue_1454():
|
|||||||
# Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
|
# Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
|
||||||
m.test_gil()
|
m.test_gil()
|
||||||
m.test_gil_from_thread()
|
m.test_gil_from_thread()
|
||||||
|
|
||||||
|
|
||||||
|
def test_python_override():
|
||||||
|
def func():
|
||||||
|
class Test(m.test_override_cache_helper):
|
||||||
|
def func(self):
|
||||||
|
return 42
|
||||||
|
|
||||||
|
return Test()
|
||||||
|
|
||||||
|
def func2():
|
||||||
|
class Test(m.test_override_cache_helper):
|
||||||
|
pass
|
||||||
|
|
||||||
|
return Test()
|
||||||
|
|
||||||
|
for _ in range(1500):
|
||||||
|
assert m.test_override_cache(func()) == 42
|
||||||
|
assert m.test_override_cache(func2()) == 0
|
||||||
|
@ -318,13 +318,21 @@ function(_pybind11_generate_lto target prefer_thin_lto)
|
|||||||
set(cxx_append ";-fno-fat-lto-objects")
|
set(cxx_append ";-fno-fat-lto-objects")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" AND prefer_thin_lto)
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "ppc64le" OR CMAKE_SYSTEM_PROCESSOR MATCHES "mips64")
|
||||||
|
set(NO_FLTO_ARCH TRUE)
|
||||||
|
else()
|
||||||
|
set(NO_FLTO_ARCH FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang"
|
||||||
|
AND prefer_thin_lto
|
||||||
|
AND NOT NO_FLTO_ARCH)
|
||||||
_pybind11_return_if_cxx_and_linker_flags_work(
|
_pybind11_return_if_cxx_and_linker_flags_work(
|
||||||
HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}"
|
HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}"
|
||||||
PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
|
PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT HAS_FLTO_THIN)
|
if(NOT HAS_FLTO_THIN AND NOT NO_FLTO_ARCH)
|
||||||
_pybind11_return_if_cxx_and_linker_flags_work(
|
_pybind11_return_if_cxx_and_linker_flags_work(
|
||||||
HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS
|
HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS
|
||||||
PYBIND11_LTO_LINKER_FLAGS)
|
PYBIND11_LTO_LINKER_FLAGS)
|
||||||
|
@ -13,7 +13,7 @@ This module sets the following variables in your project:
|
|||||||
``pybind11_VERSION``
|
``pybind11_VERSION``
|
||||||
pybind11 version in format Major.Minor.Release
|
pybind11 version in format Major.Minor.Release
|
||||||
``pybind11_VERSION_TYPE``
|
``pybind11_VERSION_TYPE``
|
||||||
pybind11 version type (dev, release)
|
pybind11 version type (``dev*`` or empty for a release)
|
||||||
``pybind11_INCLUDE_DIRS``
|
``pybind11_INCLUDE_DIRS``
|
||||||
Directories where pybind11 and python headers are located.
|
Directories where pybind11 and python headers are located.
|
||||||
``pybind11_INCLUDE_DIR``
|
``pybind11_INCLUDE_DIR``
|
||||||
@ -228,6 +228,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
|
|||||||
if(NOT pybind11_FIND_QUIETLY)
|
if(NOT pybind11_FIND_QUIETLY)
|
||||||
message(
|
message(
|
||||||
STATUS
|
STATUS
|
||||||
"Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}\" ${pybind11_VERSION_TYPE})"
|
"Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}${pybind11_VERSION_TYPE}\")"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
Loading…
Reference in New Issue
Block a user