mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +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:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
runs-on: [ubuntu-latest, windows-latest, macos-latest]
|
||||
runs-on: [ubuntu-latest, windows-2022, macos-latest]
|
||||
python:
|
||||
- '2.7'
|
||||
- '3.5'
|
||||
- '3.6'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
# - '3.11-dev'
|
||||
- 'pypy-3.7-v7.3.5'
|
||||
# - 'pypy-3.8'
|
||||
- 'pypy-3.7-v7.3.7'
|
||||
- 'pypy-3.8-v7.3.7'
|
||||
|
||||
# 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
|
||||
# existing keys match.
|
||||
#
|
||||
# We support three optional keys: args (both build), args1 (first
|
||||
# build), and args2 (second build).
|
||||
# We support an optional key: args, for cmake args
|
||||
include:
|
||||
# Just add a key
|
||||
- runs-on: ubuntu-latest
|
||||
python: 3.6
|
||||
python: '3.6'
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
-DCMAKE_CXX_FLAGS="-D_=1"
|
||||
- runs-on: windows-latest
|
||||
python: 3.6
|
||||
python: '3.6'
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
- 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 }}"
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
@ -65,7 +69,8 @@ jobs:
|
||||
python-version: ${{ matrix.python }}
|
||||
|
||||
- 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
|
||||
|
||||
- name: Setup Boost (macOS)
|
||||
@ -122,7 +127,7 @@ jobs:
|
||||
run: git clean -fdx
|
||||
|
||||
# Second build - C++17 mode and in a build directory
|
||||
- name: Configure ${{ matrix.args2 }}
|
||||
- name: Configure C++17
|
||||
run: >
|
||||
cmake -S . -B build2
|
||||
-DPYBIND11_WERROR=ON
|
||||
@ -130,7 +135,6 @@ jobs:
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
${{ matrix.args }}
|
||||
${{ matrix.args2 }}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build2 -j 2
|
||||
@ -184,6 +188,7 @@ jobs:
|
||||
# setuptools
|
||||
- name: Setuptools helpers test
|
||||
run: pytest tests/extra_setuptools
|
||||
if: "!(matrix.python == '3.5' && matrix.runs-on == 'windows-2022')"
|
||||
|
||||
|
||||
deadsnakes:
|
||||
@ -244,6 +249,8 @@ jobs:
|
||||
python -m pip install -r tests/requirements.txt
|
||||
|
||||
- name: Configure
|
||||
env:
|
||||
SETUPTOOLS_USE_DISTUTILS: stdlib
|
||||
run: >
|
||||
cmake -S . -B build
|
||||
-DCMAKE_BUILD_TYPE=Debug
|
||||
@ -552,37 +559,37 @@ jobs:
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
cmake --build build-11 --target test_cmake_build
|
||||
|
||||
- name: Configure C++17
|
||||
- name: Configure C++14
|
||||
run: |
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
cmake -S . -B build-17 \
|
||||
cmake -S . -B build-14 \
|
||||
-DPYBIND11_WERROR=ON \
|
||||
-DDOWNLOAD_CATCH=ON \
|
||||
-DDOWNLOAD_EIGEN=OFF \
|
||||
-DCMAKE_CXX_STANDARD=17 \
|
||||
-DCMAKE_CXX_STANDARD=14 \
|
||||
-DCMAKE_CXX_COMPILER=$(which icpc) \
|
||||
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)")
|
||||
|
||||
- name: Build C++17
|
||||
- name: Build C++14
|
||||
run: |
|
||||
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: |
|
||||
set +e; source /opt/intel/oneapi/setvars.sh; set -e
|
||||
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: |
|
||||
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: |
|
||||
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
|
||||
@ -704,14 +711,11 @@ jobs:
|
||||
- name: Install Doxygen
|
||||
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
|
||||
run: python3 -m sphinx -W -b html docs docs/.build
|
||||
run: pipx run nox -s docs
|
||||
|
||||
- name: Make SDist
|
||||
run: python3 setup.py sdist
|
||||
run: pipx run nox -s build -- --sdist
|
||||
|
||||
- run: git status --ignored
|
||||
|
||||
@ -723,7 +727,7 @@ jobs:
|
||||
- name: Compare Dists (headers only)
|
||||
working-directory: include
|
||||
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')")
|
||||
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:
|
||||
# Standard hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.0.1
|
||||
rev: v4.1.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@ -33,27 +33,27 @@ repos:
|
||||
exclude: ^noxfile.py$
|
||||
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.29.0
|
||||
rev: v2.29.1
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.9.3
|
||||
rev: 5.10.1
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
# Black, the code formatter, natively supports pre-commit
|
||||
- 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:
|
||||
- id: black
|
||||
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: v1.11.0
|
||||
rev: v1.12.0
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies:
|
||||
- black==21.9b0 # keep in sync with black hook
|
||||
- black==21.12b0 # keep in sync with black hook
|
||||
|
||||
# Changes tabs to spaces
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
@ -61,6 +61,12 @@ repos:
|
||||
hooks:
|
||||
- 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
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
@ -98,7 +104,7 @@ repos:
|
||||
|
||||
# Check static types with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.910-1
|
||||
rev: v0.930
|
||||
hooks:
|
||||
- id: mypy
|
||||
# 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"]
|
||||
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.7.2.1
|
||||
rev: v0.8.0.3
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
|
@ -16,6 +16,11 @@ else()
|
||||
cmake_policy(VERSION 3.22)
|
||||
endif()
|
||||
|
||||
# Avoid infinite recursion if tests include this as a subdirectory
|
||||
if(DEFINED PYBIND11_MASTER_PROJECT)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Extract project version from source
|
||||
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/include/pybind11/detail/common.h"
|
||||
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}")
|
||||
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
|
||||
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
|
||||
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
|
||||
set(lines
|
||||
@ -80,6 +80,8 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR AND NOT DEFINED PYBIND11_MASTER_
|
||||
endif()
|
||||
|
||||
set(pybind11_system "")
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
else()
|
||||
set(PYBIND11_MASTER_PROJECT OFF)
|
||||
set(pybind11_system SYSTEM)
|
||||
|
@ -106,7 +106,7 @@ goodies:
|
||||
- Binaries are generally smaller by a factor of at least 2 compared to
|
||||
equivalent bindings generated by Boost.Python. A recent pybind11
|
||||
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
|
||||
**5.8x**.
|
||||
|
||||
|
@ -18,6 +18,5 @@ ALIASES += "endrst=\endverbatim"
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \
|
||||
PY_MAJOR_VERSION=3 \
|
||||
PREDEFINED = PY_MAJOR_VERSION=3 \
|
||||
PYBIND11_NOINLINE
|
||||
|
@ -46,7 +46,7 @@ type is explicitly allowed.
|
||||
* function signatures and declares a local variable
|
||||
* '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
|
||||
|
@ -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
|
||||
``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:
|
||||
|
||||
.. 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
|
||||
as arguments and return values, refer to the section on binding :ref:`classes`.
|
||||
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| Data type | Description | Header file |
|
||||
+====================================+===========================+===============================+
|
||||
+====================================+===========================+===================================+
|
||||
| ``int8_t``, ``uint8_t`` | 8-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` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``char`` | 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` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``wchar_t`` | Wide character 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 char32_t *`` | UTF-32 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::u16string`` | STL dynamic UTF-16 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::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` |
|
||||
| ``std::u16string_view``, etc. | | |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::pair<T1, T2>`` | Pair of two custom 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::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::array<T, Size>`` | STL static 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::valarray<T>`` | STL value array | :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::unordered_map<T1, T2>`` | STL unordered map | :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::optional<T>`` | STL optional type (C++17) | :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::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::chrono::duration<...>`` | STL time duration | :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::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
|
||||
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
||||
``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++
|
||||
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
|
||||
<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``.
|
||||
|
||||
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 accepted by the function.
|
||||
arguments. Note, however, that ``py::kwargs`` must always be the last argument
|
||||
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,
|
||||
and on how to cast their entries into C++ objects. A demonstration is also
|
||||
@ -366,6 +367,8 @@ like so:
|
||||
py::class_<MyClass>("MyClass")
|
||||
.def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));
|
||||
|
||||
.. _keyword_only_arguments:
|
||||
|
||||
Keyword-only arguments
|
||||
======================
|
||||
|
||||
@ -397,6 +400,15 @@ feature does *not* require Python 3 to work.
|
||||
|
||||
.. 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
|
||||
=========================
|
||||
|
||||
|
@ -109,7 +109,7 @@ a file named :file:`example.cpp` with the following contents:
|
||||
PYBIND11_MODULE(example, m) {
|
||||
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
|
||||
|
@ -7,8 +7,100 @@ Starting with version 1.8.0, pybind11 releases use a `semantic versioning
|
||||
<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)
|
||||
---------------------
|
||||
|
@ -22,6 +22,9 @@ the version just below.
|
||||
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 ``PYBIND11_VERSION_MAJOR`` etc. in
|
||||
``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).
|
||||
(Note: if you do not use an existing tag, this creates a new lightweight tag
|
||||
for you, so you could skip the above step.)
|
||||
|
||||
- GUI method: Under `releases <https://github.com/pybind/pybind11/releases>`_
|
||||
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
|
||||
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``).
|
||||
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"``
|
||||
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
|
||||
|
||||
python3 -m pip install build
|
||||
python3 -m build
|
||||
PYBIND11_SDIST_GLOBAL=1 python3 -m build
|
||||
nox -s build
|
||||
twine upload dist/*
|
||||
|
||||
This makes SDists and wheels, and the final line uploads them.
|
||||
|
@ -1,8 +1,5 @@
|
||||
breathe==4.26.1
|
||||
# docutils 0.17 breaks HTML tags & RTD theme
|
||||
# https://github.com/sphinx-doc/sphinx/issues/9001
|
||||
docutils==0.16
|
||||
sphinx==3.3.1
|
||||
sphinx_rtd_theme==0.5.0
|
||||
sphinxcontrib-moderncmakedomain==3.17
|
||||
sphinxcontrib-svg2pdfconverter==1.1.0
|
||||
breathe==4.31.0
|
||||
sphinx==3.5.4
|
||||
sphinx_rtd_theme==1.0.0
|
||||
sphinxcontrib-moderncmakedomain==3.19
|
||||
sphinxcontrib-svg2pdfconverter==1.1.1
|
||||
|
@ -17,6 +17,10 @@ v2.9
|
||||
converted to using ``py::module_::import("types").attr("SimpleNamespace")``
|
||||
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:
|
||||
|
||||
|
@ -174,7 +174,7 @@ struct function_record {
|
||||
function_record()
|
||||
: is_constructor(false), is_new_style_constructor(false), is_stateless(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
|
||||
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
|
||||
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
|
||||
bool prepend : 1;
|
||||
|
||||
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
||||
std::uint16_t nargs;
|
||||
|
||||
/// Number of trailing arguments (counted in `nargs`) that are keyword-only
|
||||
std::uint16_t nargs_kw_only = 0;
|
||||
/// Number of leading positional arguments, which are terminated by a py::args or py::kwargs
|
||||
/// 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
|
||||
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; }
|
||||
};
|
||||
|
||||
inline void process_kw_only_arg(const arg &a, function_record *r) {
|
||||
if (!a.name || a.name[0] == '\0')
|
||||
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
|
||||
++r->nargs_kw_only;
|
||||
inline void check_kw_only_arg(const arg &a, function_record *r) {
|
||||
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0'))
|
||||
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or args() argument");
|
||||
}
|
||||
|
||||
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)
|
||||
template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
||||
static void init(const arg &a, function_record *r) {
|
||||
if (r->is_method && r->args.empty())
|
||||
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
|
||||
append_self_arg_if_needed(r);
|
||||
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> {
|
||||
static void init(const arg_v &a, function_record *r) {
|
||||
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 !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);
|
||||
|
||||
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
|
||||
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
||||
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
|
||||
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
|
||||
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());
|
||||
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 <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(detail)
|
||||
|
||||
@ -150,7 +133,8 @@ public:
|
||||
return false;
|
||||
} else {
|
||||
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;
|
||||
if (!PYBIND11_LONG_CHECK(src.ptr())) { // So: index_check(src.ptr())
|
||||
index = reinterpret_steal<object>(PyNumber_Index(src.ptr()));
|
||||
@ -224,7 +208,7 @@ public:
|
||||
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 {
|
||||
@ -237,7 +221,7 @@ public:
|
||||
static handle cast(T, return_value_policy /* policy */, handle /* parent */) {
|
||||
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> {};
|
||||
@ -280,7 +264,7 @@ public:
|
||||
|
||||
template <typename T> using cast_op_type = void*&;
|
||||
explicit operator void *&() { return value; }
|
||||
static constexpr auto name = _("capsule");
|
||||
static constexpr auto name = const_name("capsule");
|
||||
private:
|
||||
void *value = nullptr;
|
||||
};
|
||||
@ -331,7 +315,7 @@ public:
|
||||
static handle cast(bool src, return_value_policy /* policy */, handle /* parent */) {
|
||||
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:
|
||||
@ -421,7 +405,7 @@ template <typename StringType, bool IsView = false> struct string_caster {
|
||||
return s;
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(StringType, _(PYBIND11_STRING_NAME));
|
||||
PYBIND11_TYPE_CASTER(StringType, const_name(PYBIND11_STRING_NAME));
|
||||
|
||||
private:
|
||||
static handle decode_utfN(const char *buffer, ssize_t nbytes) {
|
||||
@ -558,7 +542,7 @@ public:
|
||||
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>;
|
||||
};
|
||||
|
||||
@ -595,7 +579,7 @@ public:
|
||||
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;
|
||||
|
||||
@ -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>> :
|
||||
std::true_type {};
|
||||
|
||||
template <typename T> struct handle_type_name { static constexpr auto name = _<T>(); };
|
||||
template <> struct handle_type_name<bytes> { static constexpr auto name = _(PYBIND11_BYTES_NAME); };
|
||||
template <> struct handle_type_name<int_> { static constexpr auto name = _("int"); };
|
||||
template <> struct handle_type_name<iterable> { static constexpr auto name = _("Iterable"); };
|
||||
template <> struct handle_type_name<iterator> { static constexpr auto name = _("Iterator"); };
|
||||
template <> struct handle_type_name<none> { static constexpr auto name = _("None"); };
|
||||
template <> struct handle_type_name<args> { static constexpr auto name = _("*args"); };
|
||||
template <> struct handle_type_name<kwargs> { static constexpr auto name = _("**kwargs"); };
|
||||
template <typename T> struct handle_type_name { static constexpr auto name = const_name<T>(); };
|
||||
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 = const_name("int"); };
|
||||
template <> struct handle_type_name<iterable> { static constexpr auto name = const_name("Iterable"); };
|
||||
template <> struct handle_type_name<iterator> { static constexpr auto name = const_name("Iterator"); };
|
||||
template <> struct handle_type_name<none> { static constexpr auto name = const_name("None"); };
|
||||
template <> struct handle_type_name<args> { static constexpr auto name = const_name("*args"); };
|
||||
template <> struct handle_type_name<kwargs> { static constexpr auto name = const_name("**kwargs"); };
|
||||
|
||||
template <typename type>
|
||||
struct pyobject_caster {
|
||||
@ -1130,6 +1114,9 @@ constexpr arg operator"" _a(const char *name, size_t) { return arg(name); }
|
||||
|
||||
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)
|
||||
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_kwargs = std::is_same<intrinsic_t<Arg>, kwargs>;
|
||||
// Get args/kwargs argument positions relative to the end of the argument list:
|
||||
static constexpr auto args_pos = constexpr_first<argument_is_args, Args...>() - (int) sizeof...(Args),
|
||||
kwargs_pos = constexpr_first<argument_is_kwargs, Args...>() - (int) sizeof...(Args);
|
||||
// Get kwargs argument position, or -1 if not present:
|
||||
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();
|
||||
|
||||
static constexpr bool args_kwargs_are_last = kwargs_pos >= - 1 && args_pos >= kwargs_pos - 1;
|
||||
|
||||
static_assert(args_kwargs_are_last, "py::args/py::kwargs are only permitted as the last argument(s) of a function");
|
||||
static_assert(kwargs_pos == -1 || kwargs_pos == (int) sizeof...(Args) - 1, "py::kwargs is only permitted as the last argument of a function");
|
||||
|
||||
public:
|
||||
static constexpr bool has_kwargs = kwargs_pos < 0;
|
||||
static constexpr bool has_args = args_pos < 0;
|
||||
static constexpr bool has_kwargs = kwargs_pos != -1;
|
||||
|
||||
// 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)...);
|
||||
|
||||
|
@ -97,7 +97,7 @@ public:
|
||||
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) {
|
||||
@ -195,7 +195,7 @@ public:
|
||||
localtime.tm_sec,
|
||||
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
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
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(PYBIND11_NAMESPACE)
|
||||
|
@ -10,12 +10,12 @@
|
||||
#pragma once
|
||||
|
||||
#define PYBIND11_VERSION_MAJOR 2
|
||||
#define PYBIND11_VERSION_MINOR 8
|
||||
#define PYBIND11_VERSION_PATCH 1
|
||||
#define PYBIND11_VERSION_MINOR 9
|
||||
#define PYBIND11_VERSION_PATCH 0
|
||||
|
||||
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
|
||||
// Additional convention: 0xD = dev
|
||||
#define PYBIND11_VERSION_HEX 0x02080100
|
||||
#define PYBIND11_VERSION_HEX 0x02090000
|
||||
|
||||
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name {
|
||||
#define PYBIND11_NAMESPACE_END(name) }
|
||||
@ -154,6 +154,14 @@
|
||||
// C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
|
||||
# pragma warning(disable: 4505)
|
||||
# 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
|
||||
# undef _DEBUG
|
||||
# endif
|
||||
@ -183,6 +191,21 @@
|
||||
# define PYBIND11_HAS_VARIANT 1
|
||||
#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 <frameobject.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>
|
||||
constexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); }
|
||||
constexpr descr<0> _(char const(&)[1]) { return {}; }
|
||||
constexpr descr<N - 1> const_name(char const(&text)[N]) { return descr<N - 1>(text); }
|
||||
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...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)
|
||||
template <bool B, size_t N1, size_t N2>
|
||||
constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) {
|
||||
return _(text1);
|
||||
constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const(&text1)[N1], char const(&)[N2]) {
|
||||
return const_name(text1);
|
||||
}
|
||||
template <bool B, size_t N1, size_t N2>
|
||||
constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) {
|
||||
return _(text2);
|
||||
constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const(&)[N1], char const(&text2)[N2]) {
|
||||
return const_name(text2);
|
||||
}
|
||||
|
||||
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>
|
||||
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>
|
||||
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;
|
||||
}
|
||||
|
||||
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 {}; }
|
||||
|
||||
@ -92,12 +117,12 @@ constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; }
|
||||
template <size_t N, typename... Ts, typename... Args>
|
||||
constexpr auto concat(const descr<N, Ts...> &d, const Args &...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>
|
||||
constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
|
||||
return _("{") + descr + _("}");
|
||||
return const_name("{") + descr + const_name("}");
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
|
||||
template <typename> using cast_op_type = value_and_holder &;
|
||||
explicit operator value_and_holder &() { return *value; }
|
||||
static constexpr auto name = _<value_and_holder>();
|
||||
static constexpr auto name = const_name<value_and_holder>();
|
||||
|
||||
private:
|
||||
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>;
|
||||
|
||||
public:
|
||||
static constexpr auto name = _<type>();
|
||||
static constexpr auto name = const_name<type>();
|
||||
|
||||
type_caster_base() : type_caster_base(typeid(type)) { }
|
||||
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)
|
||||
using EigenIndex = Eigen::Index;
|
||||
template<typename Scalar, int Flags, typename StorageIndex>
|
||||
using EigenMapSparseMatrix = Eigen::Map<Eigen::SparseMatrix<Scalar, Flags, StorageIndex>>;
|
||||
#else
|
||||
using EigenIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
|
||||
template<typename Scalar, int Flags, typename StorageIndex>
|
||||
using EigenMapSparseMatrix = Eigen::MappedSparseMatrix<Scalar, Flags, StorageIndex>;
|
||||
#endif
|
||||
|
||||
// Matches Eigen::Map, Eigen::Ref, blocks, etc:
|
||||
@ -80,14 +84,12 @@ template <bool EigenRowMajor> struct EigenConformable {
|
||||
// Matrix type:
|
||||
EigenConformable(EigenIndex r, EigenIndex c,
|
||||
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
|
||||
if (rstride < 0 || cstride < 0) {
|
||||
negativestrides = true;
|
||||
} else {
|
||||
stride = {EigenRowMajor ? rstride : cstride /* outer stride */,
|
||||
EigenRowMajor ? cstride : rstride /* inner stride */ };
|
||||
}
|
||||
stride{EigenRowMajor ? (rstride > 0 ? rstride : 0) : (cstride > 0 ? cstride : 0) /* outer stride */,
|
||||
EigenRowMajor ? (cstride > 0 ? cstride : 0) : (rstride > 0 ? rstride : 0) /* inner stride */ },
|
||||
negativestrides{rstride < 0 || cstride < 0} {
|
||||
|
||||
}
|
||||
// Vector type:
|
||||
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 auto descriptor =
|
||||
_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
|
||||
_("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) +
|
||||
_(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) +
|
||||
_("]") +
|
||||
const_name("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
|
||||
const_name("[") + const_name<fixed_rows>(const_name<(size_t) rows>(), const_name("m")) +
|
||||
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
|
||||
// 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
|
||||
// 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
|
||||
// *gave* a numpy.ndarray of the right type and dimensions.
|
||||
_<show_writeable>(", flags.writeable", "") +
|
||||
_<show_c_contiguous>(", flags.c_contiguous", "") +
|
||||
_<show_f_contiguous>(", flags.f_contiguous", "") +
|
||||
_("]");
|
||||
const_name<show_writeable>(", flags.writeable", "") +
|
||||
const_name<show_c_contiguous>(", flags.c_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,
|
||||
@ -573,7 +575,7 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
if (!values || !innerIndices || !outerIndices)
|
||||
return false;
|
||||
|
||||
value = Eigen::MappedSparseMatrix<Scalar,
|
||||
value = EigenMapSparseMatrix<Scalar,
|
||||
Type::Flags & (Eigen::RowMajor | Eigen::ColMajor),
|
||||
StorageIndex>(
|
||||
shape[0].cast<Index>(), shape[1].cast<Index>(), nnz,
|
||||
@ -598,8 +600,8 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
).release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(Type, _<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
|
||||
+ npy_format_descriptor<Scalar>::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(Type, const_name<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
|
||||
+ npy_format_descriptor<Scalar>::name + const_name("]"));
|
||||
};
|
||||
|
||||
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);
|
||||
#else
|
||||
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
|
||||
size_t count = strlen(safe_arg);
|
||||
# else
|
||||
@ -111,6 +118,11 @@ inline wchar_t *widen_chars(const char *safe_arg) {
|
||||
widened_arg = new wchar_t[count + 1];
|
||||
mbstowcs(widened_arg, safe_arg, count + 1);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return widened_arg;
|
||||
}
|
||||
|
@ -19,11 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
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
|
||||
// `__builtins__` key to globals if not yet present.
|
||||
// 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__"))
|
||||
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
|
||||
#else
|
||||
|
@ -113,8 +113,8 @@ public:
|
||||
return cpp_function(std::forward<Func>(f_), policy).release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(type, _("Callable[[") + concat(make_caster<Args>::name...) + _("], ")
|
||||
+ make_caster<retval_type>::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(type, const_name("Callable[[") + concat(make_caster<Args>::name...) + const_name("], ")
|
||||
+ make_caster<retval_type>::name + const_name("]"));
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
@ -39,7 +39,7 @@ class array; // Forward declaration
|
||||
|
||||
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;
|
||||
|
||||
@ -290,7 +290,7 @@ template <typename T> struct array_info_scalar {
|
||||
using type = T;
|
||||
static constexpr bool is_array = false;
|
||||
static constexpr bool is_empty = false;
|
||||
static constexpr auto extents = _("");
|
||||
static constexpr auto extents = const_name("");
|
||||
static void append_extents(list& /* shape */) { }
|
||||
};
|
||||
// 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);
|
||||
}
|
||||
|
||||
static constexpr auto extents = _<array_info<T>::is_array>(
|
||||
concat(_<N>(), array_info<T>::extents), _<N>()
|
||||
static constexpr auto extents = const_name<array_info<T>::is_array>(
|
||||
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
|
||||
@ -1021,7 +1021,7 @@ template <typename T>
|
||||
struct format_descriptor<T, detail::enable_if_t<detail::array_info<T>::is_array>> {
|
||||
static std::string format() {
|
||||
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();
|
||||
}
|
||||
};
|
||||
@ -1056,28 +1056,28 @@ struct npy_format_descriptor_name;
|
||||
|
||||
template <typename T>
|
||||
struct npy_format_descriptor_name<T, enable_if_t<std::is_integral<T>::value>> {
|
||||
static constexpr auto name = _<std::is_same<T, bool>::value>(
|
||||
_("bool"), _<std::is_signed<T>::value>("numpy.int", "numpy.uint") + _<sizeof(T)*8>()
|
||||
static constexpr auto name = const_name<std::is_same<T, bool>::value>(
|
||||
const_name("bool"), const_name<std::is_signed<T>::value>("numpy.int", "numpy.uint") + const_name<sizeof(T)*8>()
|
||||
);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
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, 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>
|
||||
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, 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 \
|
||||
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)); }
|
||||
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 };
|
||||
@ -1117,7 +1117,7 @@ private:
|
||||
public:
|
||||
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() {
|
||||
list 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>> {
|
||||
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)
|
||||
|
@ -115,7 +115,7 @@ public:
|
||||
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
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...);
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ public:
|
||||
template <typename Return, typename Class, typename... Arg, typename... Extra>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
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...);
|
||||
}
|
||||
|
||||
@ -203,7 +203,7 @@ protected:
|
||||
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");
|
||||
|
||||
/* Dispatch code which converts function arguments and performs the actual function call */
|
||||
@ -238,30 +238,37 @@ protected:
|
||||
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_attributes<Extra...>::init(extra..., rec);
|
||||
|
||||
{
|
||||
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_args = any_of<std::is_same<args, Args>...>::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_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 */
|
||||
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();
|
||||
|
||||
/* Register the function with Python from generic (non-templated) code */
|
||||
// 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));
|
||||
|
||||
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' */
|
||||
using FunctionType = Return (*)(Args...);
|
||||
constexpr bool is_function_ptr =
|
||||
@ -340,16 +347,18 @@ protected:
|
||||
/* Generate a proper function signature */
|
||||
std::string signature;
|
||||
size_t type_index = 0, arg_index = 0;
|
||||
bool is_starred = false;
|
||||
for (auto *pc = text; *pc != '\0'; ++pc) {
|
||||
const auto c = *pc;
|
||||
|
||||
if (c == '{') {
|
||||
// Write arg name for everything except *args and **kwargs.
|
||||
if (*(pc + 1) == '*')
|
||||
is_starred = *(pc + 1) == '*';
|
||||
if (is_starred)
|
||||
continue;
|
||||
// Separator for keyword-only arguments, placed before the kw
|
||||
// arguments start
|
||||
if (rec->nargs_kw_only > 0 && arg_index + rec->nargs_kw_only == args)
|
||||
// arguments start (unless we are already putting an *args)
|
||||
if (!rec->has_args && arg_index == rec->nargs_pos)
|
||||
signature += "*, ";
|
||||
if (arg_index < rec->args.size() && rec->args[arg_index].name) {
|
||||
signature += rec->args[arg_index].name;
|
||||
@ -361,7 +370,7 @@ protected:
|
||||
signature += ": ";
|
||||
} else if (c == '}') {
|
||||
// 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 += rec->args[arg_index].descr;
|
||||
}
|
||||
@ -369,6 +378,7 @@ protected:
|
||||
// argument, rather than before like *
|
||||
if (rec->nargs_pos_only > 0 && (arg_index + 1) == rec->nargs_pos_only)
|
||||
signature += ", /";
|
||||
if (!is_starred)
|
||||
arg_index++;
|
||||
} else if (c == '%') {
|
||||
const std::type_info *t = types[type_index++];
|
||||
@ -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)");
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
@ -631,7 +641,7 @@ protected:
|
||||
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
|
||||
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.
|
||||
3. Ensure that either all keyword arguments were "consumed", or that the function
|
||||
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
|
||||
if (func.has_args) --num_args; // (but don't count py::args
|
||||
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)
|
||||
continue; // Too many positional arguments for this overload
|
||||
@ -695,6 +705,10 @@ protected:
|
||||
if (bad_arg)
|
||||
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
|
||||
dict kwargs = reinterpret_borrow<dict>(kwargs_in);
|
||||
|
||||
@ -747,6 +761,10 @@ protected:
|
||||
}
|
||||
|
||||
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_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
|
||||
// can reuse it directly without copying:
|
||||
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);
|
||||
} 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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_ref = std::move(extra_args);
|
||||
}
|
||||
@ -1958,6 +1979,16 @@ inline std::pair<decltype(internals::registered_types_py)::iterator, bool> all_t
|
||||
// gets destroyed:
|
||||
weakref((PyObject *) type, cpp_function([type](handle wr) {
|
||||
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();
|
||||
})).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.
|
||||
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
|
||||
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
|
||||
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
|
||||
if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) {
|
||||
PyObject* locals = PyEval_GetLocals();
|
||||
if (locals != nullptr) {
|
||||
if (locals != nullptr && f_code->co_varnames != nullptr) {
|
||||
PyObject *self_caller = dict_getitem(
|
||||
locals, PyTuple_GET_ITEM(f_code->co_varnames, 0)
|
||||
);
|
||||
|
@ -18,6 +18,10 @@
|
||||
# include <optional>
|
||||
#endif
|
||||
|
||||
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||
# include <string_view>
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
/* A few forward declarations */
|
||||
@ -287,10 +291,10 @@ protected:
|
||||
struct borrowed_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_steal(handle);
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
public:
|
||||
// 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
|
||||
|
||||
/** \defgroup python_builtins _
|
||||
/** \defgroup python_builtins const_name
|
||||
Unless stated otherwise, the following C++ functions behave the same
|
||||
as their Python counterparts.
|
||||
*/
|
||||
@ -1085,6 +1089,20 @@ public:
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
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);
|
||||
|
||||
/** \rst
|
||||
@ -1167,6 +1185,26 @@ public:
|
||||
pybind11_fail("Unable to extract bytes contents!");
|
||||
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
|
||||
// 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) {
|
||||
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
|
||||
};
|
||||
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
/// @cond DUPLICATE
|
||||
inline memoryview memoryview::from_buffer(
|
||||
void *ptr, ssize_t itemsize, const char* format,
|
||||
detail::any_container<ssize_t> shape,
|
||||
@ -1745,7 +1790,7 @@ inline memoryview memoryview::from_buffer(
|
||||
throw error_already_set();
|
||||
return memoryview(object(obj, stolen_t{}));
|
||||
}
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
/// @endcond
|
||||
/// @} pytypes
|
||||
|
||||
/// \addtogroup python_builtins
|
||||
|
@ -78,7 +78,7 @@ template <typename Type, typename Key> struct set_caster {
|
||||
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 {
|
||||
@ -120,7 +120,7 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
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 {
|
||||
@ -166,7 +166,7 @@ public:
|
||||
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>>
|
||||
@ -223,7 +223,7 @@ public:
|
||||
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>>
|
||||
@ -273,7 +273,7 @@ template<typename Type, typename Value = typename Type::value_type> struct optio
|
||||
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)
|
||||
@ -353,7 +353,7 @@ struct variant_caster<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)
|
||||
|
@ -92,7 +92,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(T, _("os.PathLike"));
|
||||
PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
|
||||
};
|
||||
|
||||
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")
|
||||
|
||||
if "pdf" in session.posargs:
|
||||
session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
|
||||
session.run("sphinx-build", "-b", "latexpdf", ".", "_build")
|
||||
return
|
||||
|
||||
session.run("sphinx-build", "-M", "html", ".", "_build")
|
||||
session.run("sphinx-build", "-b", "html", ".", "_build")
|
||||
|
||||
if "serve" in session.posargs:
|
||||
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.run("python", "-m", "build")
|
||||
session.run("python", "-m", "build", env={"PYBIND11_GLOBAL_SDIST": "1"})
|
||||
session.log("Building normal files")
|
||||
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
|
||||
|
||||
|
||||
__version__ = "2.8.1"
|
||||
__version__ = "2.9.0"
|
||||
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 os
|
||||
import platform
|
||||
import shlex
|
||||
import shutil
|
||||
import sys
|
||||
import sysconfig
|
||||
@ -143,7 +144,12 @@ class Pybind11Extension(_Extension):
|
||||
if WIN:
|
||||
cflags += ["/EHsc", "/bigobj"]
|
||||
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:
|
||||
cflags += ["-stdlib=libc++"]
|
||||
ldflags += ["-stdlib=libc++"]
|
||||
@ -460,8 +466,14 @@ class ParallelCompile(object):
|
||||
threads = 1
|
||||
|
||||
if threads > 1:
|
||||
for _ in ThreadPool(threads).imap_unordered(_single_compile, objects):
|
||||
pool = ThreadPool(threads)
|
||||
# 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:
|
||||
for ob in objects:
|
||||
_single_compile(ob)
|
||||
|
@ -429,6 +429,14 @@ foreach(target ${test_targets})
|
||||
endif()
|
||||
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
|
||||
pybind11_find_import(pytest VERSION 3.1)
|
||||
|
||||
|
@ -8,6 +8,7 @@ import pytest
|
||||
|
||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
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])
|
||||
@ -71,13 +72,20 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
encoding="ascii",
|
||||
)
|
||||
|
||||
subprocess.check_call(
|
||||
out = subprocess.check_output(
|
||||
[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
|
||||
print(out)
|
||||
for item in tmpdir.listdir():
|
||||
print(item.basename)
|
||||
|
||||
|
@ -65,7 +65,7 @@ PYBIND11_NAMESPACE_BEGIN(pybind11)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
template<> class type_caster<RValueCaster> {
|
||||
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(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.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.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"
|
||||
pytest==4.6.9; 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
|
||||
# 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():
|
||||
mat = m.Matrix(5, 4)
|
||||
assert memoryview(mat).shape == (5, 4)
|
||||
|
@ -19,7 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
template <>
|
||||
class type_caster<ConstRefCasted> {
|
||||
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
|
||||
// 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_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
|
||||
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_return", []() { return std::u8string_view(u8"utf8 secret \U0001f382"); });
|
||||
m.def("string_view8_str", []() { return py::str{std::u8string_view{u8"abc ‽ def"}}; });
|
||||
# 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
|
||||
|
||||
// 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():
|
||||
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
|
||||
@ -299,7 +310,8 @@ def test_int_convert():
|
||||
assert noconvert(7) == 7
|
||||
cant_convert(3.14159)
|
||||
# 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():
|
||||
assert convert(Int()) == 42
|
||||
else:
|
||||
@ -334,7 +346,9 @@ def test_numpy_int_convert():
|
||||
|
||||
# The implicit conversion from np.float32 is undesirable but currently accepted.
|
||||
# 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():
|
||||
assert convert(np.float32(3.14159)) == 3
|
||||
else:
|
||||
|
@ -85,13 +85,13 @@ public:
|
||||
PYBIND11_NAMESPACE_BEGIN(pybind11)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
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; }
|
||||
static handle cast(const MoveOnlyInt &m, return_value_policy r, handle p) { return pybind11::cast(m.value, r, p); }
|
||||
};
|
||||
|
||||
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; }
|
||||
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:
|
||||
CopyOnlyInt value;
|
||||
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; }
|
||||
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) {
|
||||
|
@ -18,7 +18,12 @@ class ArgAlwaysConverts { };
|
||||
namespace pybind11 { namespace detail {
|
||||
template <> struct type_caster<ArgInspector1> {
|
||||
public:
|
||||
// Classic
|
||||
#ifndef _
|
||||
PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
|
||||
#else
|
||||
PYBIND11_TYPE_CASTER(ArgInspector1, const_name("ArgInspector1"));
|
||||
#endif
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
value.arg = "loading ArgInspector1 argument " +
|
||||
@ -33,7 +38,7 @@ public:
|
||||
};
|
||||
template <> struct type_caster<ArgInspector2> {
|
||||
public:
|
||||
PYBIND11_TYPE_CASTER(ArgInspector2, _("ArgInspector2"));
|
||||
PYBIND11_TYPE_CASTER(ArgInspector2, const_name("ArgInspector2"));
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
value.arg = "loading ArgInspector2 argument " +
|
||||
@ -48,7 +53,7 @@ public:
|
||||
};
|
||||
template <> struct type_caster<ArgAlwaysConverts> {
|
||||
public:
|
||||
PYBIND11_TYPE_CASTER(ArgAlwaysConverts, _("ArgAlwaysConverts"));
|
||||
PYBIND11_TYPE_CASTER(ArgAlwaysConverts, const_name("ArgAlwaysConverts"));
|
||||
|
||||
bool load(handle, bool convert) {
|
||||
return convert;
|
||||
@ -76,7 +81,7 @@ public:
|
||||
};
|
||||
namespace pybind11 { namespace detail {
|
||||
template <> struct type_caster<DestructionTester> {
|
||||
PYBIND11_TYPE_CASTER(DestructionTester, _("DestructionTester"));
|
||||
PYBIND11_TYPE_CASTER(DestructionTester, const_name("DestructionTester"));
|
||||
bool load(handle, bool) { return true; }
|
||||
|
||||
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)
|
||||
|
||||
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()
|
||||
|
||||
add_custom_target(
|
||||
|
@ -37,6 +37,22 @@ class PyWidget final : public Widget {
|
||||
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) {
|
||||
py::class_<Widget, PyWidget>(m, "Widget")
|
||||
.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; });
|
||||
}
|
||||
|
||||
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, ) {
|
||||
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);
|
||||
}
|
||||
|
||||
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") {
|
||||
REQUIRE_NOTHROW(py::module_::import("widget_module"));
|
||||
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 env # noqa: F401
|
||||
import env
|
||||
import pybind11_cross_module_tests as cm
|
||||
from pybind11_tests import exceptions as m
|
||||
|
||||
@ -97,6 +97,8 @@ def ignore_pytest_unraisable_warning(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
|
||||
def test_python_alreadyset_in_destructor(monkeypatch, capsys):
|
||||
hooked = False
|
||||
|
@ -56,6 +56,23 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
m.def("mixed_plus_args_kwargs_defaults", mixed_plus_both,
|
||||
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
|
||||
// PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
|
||||
#ifdef PYPY_VERSION
|
||||
@ -150,4 +167,21 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
"class_default_argument",
|
||||
[](py::object a) { return py::repr(std::move(a)); },
|
||||
"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
|
||||
)
|
||||
|
||||
# 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):
|
||||
assert m.kw_only_all(i=1, j=2) == (1, 2)
|
||||
@ -178,10 +225,23 @@ def test_keyword_only_args(msg):
|
||||
assert (
|
||||
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):
|
||||
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)
|
||||
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():
|
||||
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; }
|
||||
};
|
||||
|
||||
// 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_methods_and_attributes
|
||||
py::class_<ExampleMandA> emna(m, "ExampleMandA");
|
||||
@ -409,4 +417,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
|
||||
.def_readonly("value", &RefQualified::value)
|
||||
.def("refQualified", &RefQualified::refQualified)
|
||||
.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 "3. (arg0: {}) -> int".format(uni_name) 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();
|
||||
}
|
||||
|
||||
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
|
||||
// rather long).
|
||||
@ -378,6 +397,12 @@ TEST_SUBMODULE(virtual_functions, m) {
|
||||
// .def("str_ref", &OverrideTest::str_ref)
|
||||
.def("A_value", &OverrideTest::A_value)
|
||||
.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)
|
||||
m.test_gil()
|
||||
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")
|
||||
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(
|
||||
HAS_FLTO_THIN "-flto=thin${cxx_append}" "-flto=thin${linker_append}"
|
||||
PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS)
|
||||
endif()
|
||||
|
||||
if(NOT HAS_FLTO_THIN)
|
||||
if(NOT HAS_FLTO_THIN AND NOT NO_FLTO_ARCH)
|
||||
_pybind11_return_if_cxx_and_linker_flags_work(
|
||||
HAS_FLTO "-flto${cxx_append}" "-flto${linker_append}" PYBIND11_LTO_CXX_FLAGS
|
||||
PYBIND11_LTO_LINKER_FLAGS)
|
||||
|
@ -13,7 +13,7 @@ This module sets the following variables in your project:
|
||||
``pybind11_VERSION``
|
||||
pybind11 version in format Major.Minor.Release
|
||||
``pybind11_VERSION_TYPE``
|
||||
pybind11 version type (dev, release)
|
||||
pybind11 version type (``dev*`` or empty for a release)
|
||||
``pybind11_INCLUDE_DIRS``
|
||||
Directories where pybind11 and python headers are located.
|
||||
``pybind11_INCLUDE_DIR``
|
||||
@ -228,6 +228,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
|
||||
if(NOT pybind11_FIND_QUIETLY)
|
||||
message(
|
||||
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()
|
||||
|
Loading…
Reference in New Issue
Block a user