Unverified Commit e315e1fe authored by Henry Schreiner's avatar Henry Schreiner
Browse files

Merge branch 'master' into stable

parents 71fd5241 97976c16
FormatStyle: file FormatStyle: file
Checks: ' Checks: '
*bugprone*,
cppcoreguidelines-init-variables, cppcoreguidelines-init-variables,
cppcoreguidelines-slicing,
clang-analyzer-optin.cplusplus.VirtualCall, clang-analyzer-optin.cplusplus.VirtualCall,
google-explicit-constructor,
llvm-namespace-comment, llvm-namespace-comment,
misc-misplaced-const, misc-misplaced-const,
misc-non-copyable-objects, misc-non-copyable-objects,
...@@ -28,9 +31,10 @@ modernize-use-override, ...@@ -28,9 +31,10 @@ modernize-use-override,
modernize-use-using, modernize-use-using,
*performance*, *performance*,
readability-avoid-const-params-in-decls, readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty, readability-container-size-empty,
readability-else-after-return,
readability-delete-null-pointer, readability-delete-null-pointer,
readability-else-after-return,
readability-implicit-bool-conversion, readability-implicit-bool-conversion,
readability-make-member-function-const, readability-make-member-function-const,
readability-misplaced-array-index, readability-misplaced-array-index,
...@@ -43,6 +47,9 @@ readability-static-accessed-through-instance, ...@@ -43,6 +47,9 @@ readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace, readability-static-definition-in-anonymous-namespace,
readability-string-compare, readability-string-compare,
readability-uniqueptr-delete-release, readability-uniqueptr-delete-release,
-bugprone-exception-escape,
-bugprone-reserved-identifier,
-bugprone-unused-raii,
' '
CheckOptions: CheckOptions:
......
...@@ -68,8 +68,8 @@ nox -l ...@@ -68,8 +68,8 @@ nox -l
# Run linters # Run linters
nox -s lint nox -s lint
# Run tests # Run tests on Python 3.9
nox -s tests nox -s tests-3.9
# Build and preview docs # Build and preview docs
nox -s docs -- serve nox -s docs -- serve
......
---
name: Bug Report
about: File an issue about a bug
title: "[BUG] "
---
Make sure you've completed the following steps before submitting your issue -- thank you!
1. Make sure you've read the [documentation][]. Your issue may be addressed there.
2. Search the [issue tracker][] to verify that this hasn't already been reported. +1 or comment there if it has.
3. Consider asking first in the [Gitter chat room][].
4. Include a self-contained and minimal piece of code that reproduces the problem. If that's not possible, try to make the description as clear as possible.
a. If possible, make a PR with a new, failing test to give us a starting point to work on!
[documentation]: https://pybind11.readthedocs.io
[issue tracker]: https://github.com/pybind/pybind11/issues
[Gitter chat room]: https://gitter.im/pybind/Lobby
*After reading, remove this checklist and the template text in parentheses below.*
## Issue description
(Provide a short description, state the expected behavior and what actually happens.)
## Reproducible example code
(The code should be minimal, have no external dependencies, isolate the function(s) that cause breakage. Submit matched and complete C++ and Python snippets that can be easily compiled and run to diagnose the issue.)
name: Bug Report
description: File an issue about a bug
title: "[BUG]: "
labels: [triage]
body:
- type: markdown
attributes:
value: |
Maintainers will only make a best effort to triage PRs. Please do your best to make the issue as easy to act on as possible, and only open if clearly a problem with pybind11 (ask first if unsure).
- type: checkboxes
id: steps
attributes:
label: Required prerequisites
description: Make sure you've completed the following steps before submitting your issue -- thank you!
options:
- label: Make sure you've read the [documentation](https://pybind11.readthedocs.io). Your issue may be addressed there.
required: true
- label: Search the [issue tracker](https://github.com/pybind/pybind11/issues) and [Discussions](https:/pybind/pybind11/discussions) to verify that this hasn't already been reported. +1 or comment there if it has.
required: true
- label: Consider asking first in the [Gitter chat room](https://gitter.im/pybind/Lobby) or in a [Discussion](https:/pybind/pybind11/discussions/new).
required: false
- type: textarea
id: description
attributes:
label: Problem description
placeholder: >-
Provide a short description, state the expected behavior and what
actually happens. Include relevant information like what version of
pybind11 you are using, what system you are on, and any useful commands
/ output.
validations:
required: true
- type: textarea
id: code
attributes:
label: Reproducible example code
placeholder: >-
The code should be minimal, have no external dependencies, isolate the
function(s) that cause breakage. Submit matched and complete C++ and
Python snippets that can be easily compiled and run to diagnose the
issue. If possible, make a PR with a new, failing test to give us a
starting point to work on!
render: text
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: Ask a question
url: https://github.com/pybind/pybind11/discussions/new
about: Please ask and answer questions here, or propose new ideas.
- name: Gitter room - name: Gitter room
url: https://gitter.im/pybind/Lobby url: https://gitter.im/pybind/Lobby
about: A room for discussing pybind11 with an active community about: A room for discussing pybind11 with an active community
---
name: Feature Request
about: File an issue about adding a feature
title: "[FEAT] "
---
Make sure you've completed the following steps before submitting your issue -- thank you!
1. Check if your feature has already been mentioned / rejected / planned in other issues.
2. If those resources didn't help, consider asking in the [Gitter chat room][] to see if this is interesting / useful to a larger audience and possible to implement reasonably,
4. If you have a useful feature that passes the previous items (or not suitable for chat), please fill in the details below.
[Gitter chat room]: https://gitter.im/pybind/Lobby
*After reading, remove this checklist.*
---
name: Question
about: File an issue about unexplained behavior
title: "[QUESTION] "
---
If you have a question, please check the following first:
1. Check if your question has already been answered in the [FAQ][] section.
2. Make sure you've read the [documentation][]. Your issue may be addressed there.
3. If those resources didn't help and you only have a short question (not a bug report), consider asking in the [Gitter chat room][]
4. Search the [issue tracker][], including the closed issues, to see if your question has already been asked/answered. +1 or comment if it has been asked but has no answer.
5. If you have a more complex question which is not answered in the previous items (or not suitable for chat), please fill in the details below.
6. Include a self-contained and minimal piece of code that illustrates your question. If that's not possible, try to make the description as clear as possible.
[FAQ]: http://pybind11.readthedocs.io/en/latest/faq.html
[documentation]: https://pybind11.readthedocs.io
[issue tracker]: https://github.com/pybind/pybind11/issues
[Gitter chat room]: https://gitter.im/pybind/Lobby
*After reading, remove this checklist.*
<!--
Title (above): please place [branch_name] at the beginning if you are targeting a branch other than master. *Do not target stable*.
It is recommended to use conventional commit format, see conventionalcommits.org, but not required.
-->
## Description ## Description
<!-- Include relevant issues or PRs here, describe what changed and why --> <!-- Include relevant issues or PRs here, describe what changed and why -->
......
...@@ -75,7 +75,7 @@ jobs: ...@@ -75,7 +75,7 @@ jobs:
run: brew install boost run: brew install boost
- name: Update CMake - name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
- name: Cache wheels - name: Cache wheels
if: runner.os == 'macOS' if: runner.os == 'macOS'
...@@ -144,6 +144,24 @@ jobs: ...@@ -144,6 +144,24 @@ jobs:
if: "!(runner.os == 'Windows' && (matrix.python == 3.8 || matrix.python == 3.9 || matrix.python == '3.10-dev'))" if: "!(runner.os == 'Windows' && (matrix.python == 3.8 || matrix.python == 3.9 || matrix.python == '3.10-dev'))"
run: cmake --build build2 --target cpptest 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 - name: Interface test
run: cmake --build build2 --target test_cmake_build run: cmake --build build2 --target test_cmake_build
...@@ -193,7 +211,7 @@ jobs: ...@@ -193,7 +211,7 @@ jobs:
debug: ${{ matrix.python-debug }} debug: ${{ matrix.python-debug }}
- name: Update CMake - name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
- name: Valgrind cache - name: Valgrind cache
if: matrix.valgrind if: matrix.valgrind
...@@ -445,7 +463,7 @@ jobs: ...@@ -445,7 +463,7 @@ jobs:
run: python3 -m pip install --upgrade pip run: python3 -m pip install --upgrade pip
- name: Update CMake - name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
- name: Configure - name: Configure
shell: bash shell: bash
...@@ -594,14 +612,15 @@ jobs: ...@@ -594,14 +612,15 @@ jobs:
- name: VAR_BUILD_TYPE 7 - name: VAR_BUILD_TYPE 7
if: matrix.centos == 7 if: matrix.centos == 7
run: echo Release > VAR_BUILD_TYPE run: echo MinSizeRel > VAR_BUILD_TYPE
# Using Debug to avoid segfault that appeared around 2021-06-04, # Using Release to avoid segfault that appeared around 2021-06-04,
# apparently when the gcc version changed from 8.3 to 8.4. # apparently when the gcc version changed from 8.3 to 8.4.
- name: VAR_BUILD_TYPE 8 - name: VAR_BUILD_TYPE 8
if: matrix.centos == 8 if: matrix.centos == 8
run: echo Debug > VAR_BUILD_TYPE run: echo Release > VAR_BUILD_TYPE
# Temporally disabling EIGEN due to SSL issue in CentOS 7
- name: Configure - name: Configure
shell: bash shell: bash
run: > run: >
...@@ -664,7 +683,7 @@ jobs: ...@@ -664,7 +683,7 @@ jobs:
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)") -DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)")
working-directory: /build-tests working-directory: /build-tests
- name: Run tests - name: Python tests
run: make pytest -j 2 run: make pytest -j 2
working-directory: /build-tests working-directory: /build-tests
...@@ -738,7 +757,7 @@ jobs: ...@@ -738,7 +757,7 @@ jobs:
architecture: x86 architecture: x86
- name: Update CMake - name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
- name: Prepare MSVC - name: Prepare MSVC
uses: ilammy/msvc-dev-cmd@v1.9.0 uses: ilammy/msvc-dev-cmd@v1.9.0
...@@ -760,7 +779,7 @@ jobs: ...@@ -760,7 +779,7 @@ jobs:
- name: Build C++11 - name: Build C++11
run: cmake --build build -j 2 run: cmake --build build -j 2
- name: Run tests - name: Python tests
run: cmake --build build -t pytest run: cmake --build build -t pytest
win32-msvc2015: win32-msvc2015:
...@@ -784,7 +803,7 @@ jobs: ...@@ -784,7 +803,7 @@ jobs:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: Update CMake - name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
- name: Prepare MSVC - name: Prepare MSVC
uses: ilammy/msvc-dev-cmd@v1.9.0 uses: ilammy/msvc-dev-cmd@v1.9.0
...@@ -838,7 +857,7 @@ jobs: ...@@ -838,7 +857,7 @@ jobs:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: Update CMake - name: Update CMake
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
- name: Prepare env - name: Prepare env
run: python -m pip install -r tests/requirements.txt --prefer-binary run: python -m pip install -r tests/requirements.txt --prefer-binary
...@@ -861,32 +880,85 @@ jobs: ...@@ -861,32 +880,85 @@ jobs:
run: cmake --build build -t check run: cmake --build build -t check
mingw: mingw:
name: "🐍 3 windows-latest ${{ matrix.sys }}"
runs-on: windows-latest runs-on: windows-latest
defaults: defaults:
run: run:
shell: msys2 {0} shell: msys2 {0}
strategy:
fail-fast: false
matrix:
include:
- { sys: mingw64, env: x86_64 }
- { sys: mingw32, env: i686 }
steps: steps:
- uses: msys2/setup-msys2@v2 - uses: msys2/setup-msys2@v2
with: with:
msystem: ${{matrix.sys}}
install: >- install: >-
mingw-w64-x86_64-gcc git
mingw-w64-x86_64-python-pip mingw-w64-${{matrix.env}}-gcc
mingw-w64-x86_64-cmake mingw-w64-${{matrix.env}}-python-pip
mingw-w64-x86_64-make mingw-w64-${{matrix.env}}-python-numpy
mingw-w64-x86_64-python-pytest mingw-w64-${{matrix.env}}-python-scipy
mingw-w64-x86_64-eigen3 mingw-w64-${{matrix.env}}-cmake
mingw-w64-x86_64-boost mingw-w64-${{matrix.env}}-make
mingw-w64-x86_64-catch mingw-w64-${{matrix.env}}-python-pytest
mingw-w64-${{matrix.env}}-eigen3
mingw-w64-${{matrix.env}}-boost
mingw-w64-${{matrix.env}}-catch
- uses: actions/checkout@v1 - uses: actions/checkout@v2
- name: Configure - name: Configure C++11
# LTO leads to many undefined reference like # LTO leads to many undefined reference like
# `pybind11::detail::function_call::function_call(pybind11::detail::function_call&&) # `pybind11::detail::function_call::function_call(pybind11::detail::function_call&&)
run: cmake -G "MinGW Makefiles" -S . -B build run: cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=11 -S . -B build
- name: Build - name: Build C++11
run: cmake --build build -j 2 run: cmake --build build -j 2
- name: Python tests - name: Python tests C++11
run: cmake --build build --target pytest run: cmake --build build --target pytest -j 2
- name: C++11 tests
run: cmake --build build --target cpptest -j 2
- name: Interface test C++11
run: cmake --build build --target test_cmake_build
- name: Clean directory
run: git clean -fdx
- name: Configure C++14
run: cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=14 -S . -B build2
- name: Build C++14
run: cmake --build build2 -j 2
- name: Python tests C++14
run: cmake --build build2 --target pytest -j 2
- name: C++14 tests
run: cmake --build build2 --target cpptest -j 2
- name: Interface test C++14
run: cmake --build build2 --target test_cmake_build
- name: Clean directory
run: git clean -fdx
- name: Configure C++17
run: cmake -G "MinGW Makefiles" -DCMAKE_CXX_STANDARD=17 -S . -B build3
- name: Build C++17
run: cmake --build build3 -j 2
- name: Python tests C++17
run: cmake --build build3 --target pytest -j 2
- name: C++17 tests
run: cmake --build build3 --target cpptest -j 2
- name: Interface test C++17
run: cmake --build build3 --target test_cmake_build
...@@ -18,7 +18,7 @@ jobs: ...@@ -18,7 +18,7 @@ jobs:
matrix: matrix:
runs-on: [ubuntu-latest, macos-latest, windows-latest] runs-on: [ubuntu-latest, macos-latest, windows-latest]
arch: [x64] arch: [x64]
cmake: [3.18] cmake: ["3.21"]
include: include:
- runs-on: ubuntu-latest - runs-on: ubuntu-latest
...@@ -55,7 +55,7 @@ jobs: ...@@ -55,7 +55,7 @@ jobs:
# An action for adding a specific version of CMake: # An action for adding a specific version of CMake:
# https://github.com/jwlawson/actions-setup-cmake # https://github.com/jwlawson/actions-setup-cmake
- name: Setup CMake ${{ matrix.cmake }} - name: Setup CMake ${{ matrix.cmake }}
uses: jwlawson/actions-setup-cmake@v1.9 uses: jwlawson/actions-setup-cmake@v1.11
with: with:
cmake-version: ${{ matrix.cmake }} cmake-version: ${{ matrix.cmake }}
......
...@@ -19,8 +19,10 @@ repos: ...@@ -19,8 +19,10 @@ repos:
hooks: hooks:
- id: check-added-large-files - id: check-added-large-files
- id: check-case-conflict - id: check-case-conflict
- id: check-docstring-first
- id: check-merge-conflict - id: check-merge-conflict
- id: check-symlinks - id: check-symlinks
- id: check-toml
- id: check-yaml - id: check-yaml
- id: debug-statements - id: debug-statements
- id: end-of-file-fixer - id: end-of-file-fixer
...@@ -31,18 +33,27 @@ repos: ...@@ -31,18 +33,27 @@ repos:
exclude: ^noxfile.py$ exclude: ^noxfile.py$
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.23.1 rev: v2.29.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
- repo: https://github.com/PyCQA/isort
rev: 5.9.3
hooks:
- 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.7b0 rev: 21.9b0 # Keep in sync with blacken-docs
hooks: hooks:
- id: black - id: black
# By default, this ignores pyi files, though black supports them
types: [text] - repo: https://github.com/asottile/blacken-docs
files: \.pyi?$ rev: v1.11.0
hooks:
- id: blacken-docs
additional_dependencies:
- black==21.9b0 # 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
...@@ -50,6 +61,12 @@ repos: ...@@ -50,6 +61,12 @@ repos:
hooks: hooks:
- id: remove-tabs - id: remove-tabs
# Autoremoves unused imports
- repo: https://github.com/hadialqattan/pycln
rev: v1.0.3
hooks:
- id: pycln
# Flake8 also supports pre-commit natively (same author) # Flake8 also supports pre-commit natively (same author)
- repo: https://github.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: 3.9.2 rev: 3.9.2
...@@ -81,7 +98,7 @@ repos: ...@@ -81,7 +98,7 @@ repos:
# Checks the manifest for missing files (native support) # Checks the manifest for missing files (native support)
- repo: https://github.com/mgedmin/check-manifest - repo: https://github.com/mgedmin/check-manifest
rev: "0.46" rev: "0.47"
hooks: hooks:
- id: check-manifest - id: check-manifest
# This is a slow hook, so only run this if --hook-stage manual is passed # This is a slow hook, so only run this if --hook-stage manual is passed
...@@ -95,10 +112,10 @@ repos: ...@@ -95,10 +112,10 @@ repos:
exclude: ".supp$" exclude: ".supp$"
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.7.2.1
hooks: hooks:
- id: shellcheck - id: shellcheck
# The original pybind11 checks for a few C++ style items # The original pybind11 checks for a few C++ style items
- repo: local - repo: local
......
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
cmake_minimum_required(VERSION 3.4) cmake_minimum_required(VERSION 3.4)
# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with # The `cmake_minimum_required(VERSION 3.4...3.21)` syntax does not work with
# some versions of VS that have a patched CMake 3.11. This forces us to emulate # some versions of VS that have a patched CMake 3.11. This forces us to emulate
# the behavior using the following workaround: # the behavior using the following workaround:
if(${CMAKE_VERSION} VERSION_LESS 3.18) if(${CMAKE_VERSION} VERSION_LESS 3.21)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}) cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else() else()
cmake_policy(VERSION 3.18) cmake_policy(VERSION 3.21)
endif() endif()
# Extract project version from source # Extract project version from source
...@@ -89,6 +89,9 @@ endif() ...@@ -89,6 +89,9 @@ endif()
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT}) option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT}) option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
option(PYBIND11_NOPYTHON "Disable search for Python" OFF) option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
set(PYBIND11_INTERNALS_VERSION
""
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
cmake_dependent_option( cmake_dependent_option(
USE_PYTHON_INCLUDE_DIR USE_PYTHON_INCLUDE_DIR
...@@ -183,6 +186,10 @@ if(NOT TARGET pybind11_headers) ...@@ -183,6 +186,10 @@ if(NOT TARGET pybind11_headers)
target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals
cxx_right_angle_brackets) cxx_right_angle_brackets)
if(NOT "${PYBIND11_INTERNALS_VERSION}" STREQUAL "")
target_compile_definitions(
pybind11_headers INTERFACE "PYBIND11_INTERNALS_VERSION=${PYBIND11_INTERNALS_VERSION}")
endif()
else() else()
# It is invalid to install a target twice, too. # It is invalid to install a target twice, too.
set(PYBIND11_INSTALL OFF) set(PYBIND11_INSTALL OFF)
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
**pybind11 — Seamless operability between C++11 and Python** **pybind11 — Seamless operability between C++11 and Python**
|Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |CI| |Build status| |Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |GitHub Discussions| |CI| |Build status|
|Repology| |PyPI package| |Conda-forge| |Python Versions| |Repology| |PyPI package| |Conda-forge| |Python Versions|
...@@ -134,9 +134,9 @@ About ...@@ -134,9 +134,9 @@ About
This project was created by `Wenzel This project was created by `Wenzel
Jakob <http://rgl.epfl.ch/people/wjakob>`_. Significant features and/or Jakob <http://rgl.epfl.ch/people/wjakob>`_. Significant features and/or
improvements to the code were contributed by Jonas Adler, Lori A. Burns, improvements to the code were contributed by Jonas Adler, Lori A. Burns,
Sylvain Corlay, Eric Cousineau, Ralf Grosse-Kunstleve, Trent Houliston, Axel Sylvain Corlay, Eric Cousineau, Aaron Gokaslan, Ralf Grosse-Kunstleve, Trent Houliston, Axel
Huebl, @hulucc, Yannick Jadoul, Sergey Lyskov Johan Mabille, Tomasz Miąsko, Huebl, @hulucc, Yannick Jadoul, Sergey Lyskov Johan Mabille, Tomasz Miąsko,
Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim
Schellart, Henry Schreiner, Ivan Smirnov, Boris Staletic, and Patrick Stewart. Schellart, Henry Schreiner, Ivan Smirnov, Boris Staletic, and Patrick Stewart.
We thank Google for a generous financial contribution to the continuous We thank Google for a generous financial contribution to the continuous
...@@ -176,3 +176,5 @@ to the terms and conditions of this license. ...@@ -176,3 +176,5 @@ to the terms and conditions of this license.
:target: https://repology.org/project/python:pybind11/versions :target: https://repology.org/project/python:pybind11/versions
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/pybind11.svg .. |Python Versions| image:: https://img.shields.io/pypi/pyversions/pybind11.svg
:target: https://pypi.org/project/pybind11/ :target: https://pypi.org/project/pybind11/
.. |GitHub Discussions| image:: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github
:target: https://github.com/pybind/pybind11/discussions
...@@ -26,7 +26,9 @@ The following Python snippet demonstrates the intended usage from the Python sid ...@@ -26,7 +26,9 @@ The following Python snippet demonstrates the intended usage from the Python sid
def __int__(self): def __int__(self):
return 123 return 123
from example import print from example import print
print(A()) print(A())
To register the necessary conversion routines, it is necessary to add an To register the necessary conversion routines, it is necessary to add an
......
...@@ -112,7 +112,7 @@ example: ...@@ -112,7 +112,7 @@ example:
.. code-block:: python .. code-block:: python
a = MyClass() a = MyClass()
m = a.get_matrix() # flags.writeable = True, flags.owndata = False m = a.get_matrix() # flags.writeable = True, flags.owndata = False
v = a.view_matrix() # flags.writeable = False, flags.owndata = False v = a.view_matrix() # flags.writeable = False, flags.owndata = False
c = a.copy_matrix() # flags.writeable = True, flags.owndata = True c = a.copy_matrix() # flags.writeable = True, flags.owndata = True
# m[5,6] and v[5,6] refer to the same element, c[5,6] does not. # m[5,6] and v[5,6] refer to the same element, c[5,6] does not.
...@@ -203,7 +203,7 @@ adding the ``order='F'`` option when creating an array: ...@@ -203,7 +203,7 @@ adding the ``order='F'`` option when creating an array:
.. code-block:: python .. code-block:: python
myarray = np.array(source, order='F') myarray = np.array(source, order="F")
Such an object will be passable to a bound function accepting an Such an object will be passable to a bound function accepting an
``Eigen::Ref<MatrixXd>`` (or similar column-major Eigen type). ``Eigen::Ref<MatrixXd>`` (or similar column-major Eigen type).
......
...@@ -36,13 +36,13 @@ everywhere <http://utf8everywhere.org/>`_. ...@@ -36,13 +36,13 @@ everywhere <http://utf8everywhere.org/>`_.
} }
); );
.. code-block:: python .. code-block:: pycon
>>> utf8_test('🎂') >>> utf8_test("🎂")
utf-8 is icing on the cake. utf-8 is icing on the cake.
🎂 🎂
>>> utf8_charptr('🍕') >>> utf8_charptr("🍕")
My favorite food is My favorite food is
🍕 🍕
...@@ -80,7 +80,7 @@ raise a ``UnicodeDecodeError``. ...@@ -80,7 +80,7 @@ raise a ``UnicodeDecodeError``.
} }
); );
.. code-block:: python .. code-block:: pycon
>>> isinstance(example.std_string_return(), str) >>> isinstance(example.std_string_return(), str)
True True
...@@ -114,7 +114,7 @@ conversion has the same overhead as implicit conversion. ...@@ -114,7 +114,7 @@ conversion has the same overhead as implicit conversion.
} }
); );
.. code-block:: python .. code-block:: pycon
>>> str_output() >>> str_output()
'Send your résumé to Alice in HR' 'Send your résumé to Alice in HR'
...@@ -143,7 +143,7 @@ returned to Python as ``bytes``, then one can return the data as a ...@@ -143,7 +143,7 @@ returned to Python as ``bytes``, then one can return the data as a
} }
); );
.. code-block:: python .. code-block:: pycon
>>> example.return_bytes() >>> example.return_bytes()
b'\xba\xd0\xba\xd0' b'\xba\xd0\xba\xd0'
...@@ -160,7 +160,7 @@ encoding, but cannot convert ``std::string`` back to ``bytes`` implicitly. ...@@ -160,7 +160,7 @@ encoding, but cannot convert ``std::string`` back to ``bytes`` implicitly.
} }
); );
.. code-block:: python .. code-block:: pycon
>>> isinstance(example.asymmetry(b"have some bytes"), str) >>> isinstance(example.asymmetry(b"have some bytes"), str)
True True
...@@ -229,16 +229,16 @@ character. ...@@ -229,16 +229,16 @@ character.
m.def("pass_char", [](char c) { return c; }); m.def("pass_char", [](char c) { return c; });
m.def("pass_wchar", [](wchar_t w) { return w; }); m.def("pass_wchar", [](wchar_t w) { return w; });
.. code-block:: python .. code-block:: pycon
>>> example.pass_char('A') >>> example.pass_char("A")
'A' 'A'
While C++ will cast integers to character types (``char c = 0x65;``), pybind11 While C++ will cast integers to character types (``char c = 0x65;``), pybind11
does not convert Python integers to characters implicitly. The Python function does not convert Python integers to characters implicitly. The Python function
``chr()`` can be used to convert integers to characters. ``chr()`` can be used to convert integers to characters.
.. code-block:: python .. code-block:: pycon
>>> example.pass_char(0x65) >>> example.pass_char(0x65)
TypeError TypeError
...@@ -259,17 +259,17 @@ a combining acute accent). The combining character will be lost if the ...@@ -259,17 +259,17 @@ a combining acute accent). The combining character will be lost if the
two-character sequence is passed as an argument, even though it renders as a two-character sequence is passed as an argument, even though it renders as a
single grapheme. single grapheme.
.. code-block:: python .. code-block:: pycon
>>> example.pass_wchar('é') >>> example.pass_wchar("é")
'é' 'é'
>>> combining_e_acute = 'e' + '\u0301' >>> combining_e_acute = "e" + "\u0301"
>>> combining_e_acute >>> combining_e_acute
'é' 'é'
>>> combining_e_acute == 'é' >>> combining_e_acute == "é"
False False
>>> example.pass_wchar(combining_e_acute) >>> example.pass_wchar(combining_e_acute)
...@@ -278,9 +278,9 @@ single grapheme. ...@@ -278,9 +278,9 @@ single grapheme.
Normalizing combining characters before passing the character literal to C++ Normalizing combining characters before passing the character literal to C++
may resolve *some* of these issues: may resolve *some* of these issues:
.. code-block:: python .. code-block:: pycon
>>> example.pass_wchar(unicodedata.normalize('NFC', combining_e_acute)) >>> example.pass_wchar(unicodedata.normalize("NFC", combining_e_acute))
'é' 'é'
In some languages (Thai for example), there are `graphemes that cannot be In some languages (Thai for example), there are `graphemes that cannot be
......
...@@ -136,7 +136,7 @@ a virtual method call. ...@@ -136,7 +136,7 @@ a virtual method call.
u'woof! woof! woof! ' u'woof! woof! woof! '
>>> class Cat(Animal): >>> class Cat(Animal):
... def go(self, n_times): ... def go(self, n_times):
... return "meow! " * n_times ... return "meow! " * n_times
... ...
>>> c = Cat() >>> c = Cat()
>>> call_go(c) >>> call_go(c)
...@@ -159,8 +159,9 @@ Here is an example: ...@@ -159,8 +159,9 @@ Here is an example:
class Dachshund(Dog): class Dachshund(Dog):
def __init__(self, name): def __init__(self, name):
Dog.__init__(self) # Without this, a TypeError is raised. Dog.__init__(self) # Without this, a TypeError is raised.
self.name = name self.name = name
def bark(self): def bark(self):
return "yap!" return "yap!"
...@@ -1153,6 +1154,7 @@ error: ...@@ -1153,6 +1154,7 @@ error:
>>> class PyFinalChild(IsFinal): >>> class PyFinalChild(IsFinal):
... pass ... pass
...
TypeError: type 'IsFinal' is not an acceptable base type TypeError: type 'IsFinal' is not an acceptable base type
.. note:: This attribute is currently ignored on PyPy .. note:: This attribute is currently ignored on PyPy
...@@ -1247,7 +1249,7 @@ Accessing the type object ...@@ -1247,7 +1249,7 @@ Accessing the type object
You can get the type object from a C++ class that has already been registered using: You can get the type object from a C++ class that has already been registered using:
.. code-block:: python .. code-block:: cpp
py::type T_py = py::type::of<T>(); py::type T_py = py::type::of<T>();
...@@ -1259,3 +1261,37 @@ object, just like ``type(ob)`` in Python. ...@@ -1259,3 +1261,37 @@ object, just like ``type(ob)`` in Python.
Other types, like ``py::type::of<int>()``, do not work, see :ref:`type-conversions`. Other types, like ``py::type::of<int>()``, do not work, see :ref:`type-conversions`.
.. versionadded:: 2.6 .. versionadded:: 2.6
Custom type setup
=================
For advanced use cases, such as enabling garbage collection support, you may
wish to directly manipulate the `PyHeapTypeObject` corresponding to a
``py::class_`` definition.
You can do that using ``py::custom_type_setup``:
.. code-block:: cpp
struct OwnsPythonObjects {
py::object value = py::none();
};
py::class_<OwnsPythonObjects> cls(
m, "OwnsPythonObjects", py::custom_type_setup([](PyHeapTypeObject *heap_type) {
auto *type = &heap_type->ht_type;
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
type->tp_traverse = [](PyObject *self_base, visitproc visit, void *arg) {
auto &self = py::cast<OwnsPythonObjects&>(py::handle(self_base));
Py_VISIT(self.value.ptr());
return 0;
};
type->tp_clear = [](PyObject *self_base) {
auto &self = py::cast<OwnsPythonObjects&>(py::handle(self_base));
self.value = py::none();
return 0;
};
}));
cls.def(py::init<>());
cls.def_readwrite("value", &OwnsPythonObjects::value);
.. versionadded:: 2.8
...@@ -122,6 +122,7 @@ embedding the interpreter. This makes it easy to import local Python files: ...@@ -122,6 +122,7 @@ embedding the interpreter. This makes it easy to import local Python files:
"""calc.py located in the working directory""" """calc.py located in the working directory"""
def add(i, j): def add(i, j):
return i + j return i + j
......
...@@ -75,9 +75,10 @@ Registering custom translators ...@@ -75,9 +75,10 @@ Registering custom translators
If the default exception conversion policy described above is insufficient, If the default exception conversion policy described above is insufficient,
pybind11 also provides support for registering custom exception translators. pybind11 also provides support for registering custom exception translators.
To register a simple exception conversion that translates a C++ exception into Similar to pybind11 classes, exception translators can be local to the module
a new Python exception using the C++ exception's ``what()`` method, a helper they are defined in or global to the entire python session. To register a simple
function is available: exception conversion that translates a C++ exception into a new Python exception
using the C++ exception's ``what()`` method, a helper function is available:
.. code-block:: cpp .. code-block:: cpp
...@@ -87,12 +88,20 @@ This call creates a Python exception class with the name ``PyExp`` in the given ...@@ -87,12 +88,20 @@ This call creates a Python exception class with the name ``PyExp`` in the given
module and automatically converts any encountered exceptions of type ``CppExp`` module and automatically converts any encountered exceptions of type ``CppExp``
into Python exceptions of type ``PyExp``. into Python exceptions of type ``PyExp``.
A matching function is available for registering a local exception translator:
.. code-block:: cpp
py::register_local_exception<CppExp>(module, "PyExp");
It is possible to specify base class for the exception using the third It is possible to specify base class for the exception using the third
parameter, a `handle`: parameter, a `handle`:
.. code-block:: cpp .. code-block:: cpp
py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError); py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
py::register_local_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
Then `PyExp` can be caught both as `PyExp` and `RuntimeError`. Then `PyExp` can be caught both as `PyExp` and `RuntimeError`.
...@@ -100,16 +109,18 @@ The class objects of the built-in Python exceptions are listed in the Python ...@@ -100,16 +109,18 @@ The class objects of the built-in Python exceptions are listed in the Python
documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_. documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_.
The default base class is `PyExc_Exception`. The default base class is `PyExc_Exception`.
When more advanced exception translation is needed, the function When more advanced exception translation is needed, the functions
``py::register_exception_translator(translator)`` can be used to register ``py::register_exception_translator(translator)`` and
``py::register_local_exception_translator(translator)`` can be used to register
functions that can translate arbitrary exception types (and which may include functions that can translate arbitrary exception types (and which may include
additional logic to do so). The function takes a stateless callable (e.g. a additional logic to do so). The functions takes a stateless callable (e.g. a
function pointer or a lambda function without captured variables) with the call function pointer or a lambda function without captured variables) with the call
signature ``void(std::exception_ptr)``. signature ``void(std::exception_ptr)``.
When a C++ exception is thrown, the registered exception translators are tried When a C++ exception is thrown, the registered exception translators are tried
in reverse order of registration (i.e. the last registered translator gets the in reverse order of registration (i.e. the last registered translator gets the
first shot at handling the exception). first shot at handling the exception). All local translators will be tried
before a global translator is tried.
Inside the translator, ``std::rethrow_exception`` should be used within Inside the translator, ``std::rethrow_exception`` should be used within
a try block to re-throw the exception. One or more catch clauses to catch a try block to re-throw the exception. One or more catch clauses to catch
...@@ -168,6 +179,53 @@ section. ...@@ -168,6 +179,53 @@ section.
with ``-fvisibility=hidden``. Therefore exceptions that are used across ABI boundaries need to be explicitly exported, as exercised in ``tests/test_exceptions.h``. with ``-fvisibility=hidden``. Therefore exceptions that are used across ABI boundaries need to be explicitly exported, as exercised in ``tests/test_exceptions.h``.
See also: "Problems with C++ exceptions" under `GCC Wiki <https://gcc.gnu.org/wiki/Visibility>`_. See also: "Problems with C++ exceptions" under `GCC Wiki <https://gcc.gnu.org/wiki/Visibility>`_.
Local vs Global Exception Translators
=====================================
When a global exception translator is registered, it will be applied across all
modules in the reverse order of registration. This can create behavior where the
order of module import influences how exceptions are translated.
If module1 has the following translator:
.. code-block:: cpp
py::register_exception_translator([](std::exception_ptr p) {
try {
if (p) std::rethrow_exception(p);
} catch (const std::invalid_argument &e) {
PyErr_SetString("module1 handled this")
}
}
and module2 has the following similar translator:
.. code-block:: cpp
py::register_exception_translator([](std::exception_ptr p) {
try {
if (p) std::rethrow_exception(p);
} catch (const std::invalid_argument &e) {
PyErr_SetString("module2 handled this")
}
}
then which translator handles the invalid_argument will be determined by the
order that module1 and module2 are imported. Since exception translators are
applied in the reverse order of registration, which ever module was imported
last will "win" and that translator will be applied.
If there are multiple pybind11 modules that share exception types (either
standard built-in or custom) loaded into a single python instance and
consistent error handling behavior is needed, then local translators should be
used.
Changing the previous example to use ``register_local_exception_translator``
would mean that when invalid_argument is thrown in the module2 code, the
module2 translator will always handle it, while in module1, the module1
translator will do the same.
.. _handling_python_exceptions_cpp: .. _handling_python_exceptions_cpp:
Handling exceptions from Python in C++ Handling exceptions from Python in C++
...@@ -265,6 +323,34 @@ Alternately, to ignore the error, call `PyErr_Clear ...@@ -265,6 +323,34 @@ Alternately, to ignore the error, call `PyErr_Clear
Any Python error must be thrown or cleared, or Python/pybind11 will be left in Any Python error must be thrown or cleared, or Python/pybind11 will be left in
an invalid state. an invalid state.
Chaining exceptions ('raise from')
==================================
In Python 3.3 a mechanism for indicating that exceptions were caused by other
exceptions was introduced:
.. code-block:: py
try:
print(1 / 0)
except Exception as exc:
raise RuntimeError("could not divide by zero") from exc
To do a similar thing in pybind11, you can use the ``py::raise_from`` function. It
sets the current python error indicator, so to continue propagating the exception
you should ``throw py::error_already_set()`` (Python 3 only).
.. code-block:: cpp
try {
py::eval("print(1 / 0"));
} catch (py::error_already_set &e) {
py::raise_from(e, PyExc_RuntimeError, "could not divide by zero");
throw py::error_already_set();
}
.. versionadded:: 2.8
.. _unraisable_exceptions: .. _unraisable_exceptions:
Handling unraisable exceptions Handling unraisable exceptions
......
...@@ -272,7 +272,7 @@ And used in Python as usual: ...@@ -272,7 +272,7 @@ And used in Python as usual:
.. code-block:: pycon .. code-block:: pycon
>>> print_dict({'foo': 123, 'bar': 'hello'}) >>> print_dict({"foo": 123, "bar": "hello"})
key=foo, value=123 key=foo, value=123
key=bar, value=hello key=bar, value=hello
...@@ -377,10 +377,11 @@ argument in a function definition: ...@@ -377,10 +377,11 @@ argument in a function definition:
def f(a, *, b): # a can be positional or via keyword; b must be via keyword def f(a, *, b): # a can be positional or via keyword; b must be via keyword
pass pass
f(a=1, b=2) # good f(a=1, b=2) # good
f(b=2, a=1) # good f(b=2, a=1) # good
f(1, b=2) # good f(1, b=2) # good
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
Pybind11 provides a ``py::kw_only`` object that allows you to implement Pybind11 provides a ``py::kw_only`` object that allows you to implement
the same behaviour by specifying the object between positional and keyword-only the same behaviour by specifying the object between positional and keyword-only
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment