mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Merge branch 'master' into stable
This commit is contained in:
commit
10889fe897
@ -9,7 +9,7 @@ platform:
|
||||
- x86
|
||||
environment:
|
||||
matrix:
|
||||
- PYTHON: 36
|
||||
- PYTHON: 38
|
||||
CONFIG: Debug
|
||||
install:
|
||||
- ps: |
|
||||
|
11
.github/labeler.yml
vendored
11
.github/labeler.yml
vendored
@ -1,8 +1,13 @@
|
||||
docs:
|
||||
- any:
|
||||
- 'docs/**/*.rst'
|
||||
all:
|
||||
- changed-files:
|
||||
- all-globs-to-all-files:
|
||||
- '!docs/changelog.rst'
|
||||
- '!docs/upgrade.rst'
|
||||
- base-branch: "^(?!dependabot).*"
|
||||
- base-branch: "^(?!pre-commit-ci).*"
|
||||
|
||||
ci:
|
||||
- '.github/workflows/*.yml'
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- '.github/workflows/*.yml'
|
||||
|
9
.github/labeler_merged.yml
vendored
9
.github/labeler_merged.yml
vendored
@ -1,3 +1,8 @@
|
||||
# Add 'needs changelog` label to any change to code files as long as the `CHANGELOG` hasn't changed
|
||||
# Skip dependabot and pre-commit-ci PRs
|
||||
needs changelog:
|
||||
- all:
|
||||
- '!docs/changelog.rst'
|
||||
- all:
|
||||
- changed-files:
|
||||
- all-globs-to-all-files: "!docs/changelog.rst"
|
||||
- base-branch: "^(?!dependabot).*"
|
||||
- base-branch: "^(?!pre-commit-ci).*"
|
||||
|
101
.github/workflows/ci.yml
vendored
101
.github/workflows/ci.yml
vendored
@ -30,13 +30,12 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
runs-on: [ubuntu-20.04, windows-2022, macos-latest]
|
||||
runs-on: [ubuntu-20.04, windows-2022, macos-13]
|
||||
python:
|
||||
- '3.6'
|
||||
- '3.8'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
- '3.11'
|
||||
- '3.12'
|
||||
- '3.13'
|
||||
- 'pypy-3.8'
|
||||
- 'pypy-3.9'
|
||||
- 'pypy-3.10'
|
||||
@ -49,21 +48,26 @@ jobs:
|
||||
include:
|
||||
# Just add a key
|
||||
- runs-on: ubuntu-20.04
|
||||
python: '3.6'
|
||||
python: '3.8'
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
-DCMAKE_CXX_FLAGS="-D_=1"
|
||||
exercise_D_: 1
|
||||
- runs-on: ubuntu-20.04
|
||||
python: 'pypy-3.8'
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
- runs-on: windows-2019
|
||||
python: '3.6'
|
||||
python: '3.8'
|
||||
args: >
|
||||
-DPYBIND11_FINDPYTHON=ON
|
||||
# Inject a couple Windows 2019 runs
|
||||
- runs-on: windows-2019
|
||||
python: '3.9'
|
||||
# Extra ubuntu latest job
|
||||
- runs-on: ubuntu-latest
|
||||
python: '3.11'
|
||||
|
||||
|
||||
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
@ -75,10 +79,11 @@ jobs:
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
allow-prereleases: true
|
||||
|
||||
- name: Setup Boost (Linux)
|
||||
# Can't use boost + define _
|
||||
if: runner.os == 'Linux' && matrix.python != '3.6'
|
||||
if: runner.os == 'Linux' && matrix.exercise_D_ != 1
|
||||
run: sudo apt-get install libboost-dev
|
||||
|
||||
- name: Setup Boost (macOS)
|
||||
@ -129,8 +134,6 @@ jobs:
|
||||
run: cmake --build . --target pytest -j 2
|
||||
|
||||
- name: C++11 tests
|
||||
# TODO: Figure out how to load the DLL on Python 3.8+
|
||||
if: "!(runner.os == 'Windows' && (matrix.python == 3.8 || matrix.python == 3.9 || matrix.python == '3.10' || matrix.python == '3.11' || matrix.python == 'pypy-3.8'))"
|
||||
run: cmake --build . --target cpptest -j 2
|
||||
|
||||
- name: Interface test C++11
|
||||
@ -160,8 +163,6 @@ jobs:
|
||||
run: cmake --build build2 --target pytest
|
||||
|
||||
- name: C++ tests
|
||||
# TODO: Figure out how to load the DLL on Python 3.8+
|
||||
if: "!(runner.os == 'Windows' && (matrix.python == 3.8 || matrix.python == 3.9 || matrix.python == '3.10' || matrix.python == '3.11' || matrix.python == 'pypy-3.8'))"
|
||||
run: cmake --build build2 --target cpptest
|
||||
|
||||
# Third build - C++17 mode with unstable ABI
|
||||
@ -192,6 +193,35 @@ jobs:
|
||||
pytest tests/extra_setuptools
|
||||
if: "!(matrix.runs-on == 'windows-2022')"
|
||||
|
||||
manylinux:
|
||||
name: Manylinux on 🐍 3.13t • GIL
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 40
|
||||
container: quay.io/pypa/musllinux_1_2_x86_64:latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Prepare venv
|
||||
run: python3.13t -m venv .venv
|
||||
|
||||
- name: Install Python deps
|
||||
run: .venv/bin/pip install -r tests/requirements.txt
|
||||
|
||||
- name: Configure C++11
|
||||
run: >
|
||||
cmake -S. -Bbuild
|
||||
-DPYBIND11_WERROR=ON
|
||||
-DDOWNLOAD_CATCH=ON
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DPython_ROOT_DIR=.venv
|
||||
|
||||
- name: Build C++11
|
||||
run: cmake --build build -j2
|
||||
|
||||
- name: Python tests C++11
|
||||
run: cmake --build build --target pytest -j2
|
||||
|
||||
deadsnakes:
|
||||
strategy:
|
||||
@ -626,15 +656,13 @@ jobs:
|
||||
cmake --build build-17 --target test_cmake_build
|
||||
|
||||
|
||||
# Testing on CentOS (manylinux uses a centos base, and this is an easy way
|
||||
# to get GCC 4.8, which is the manylinux1 compiler).
|
||||
# Testing on CentOS (manylinux uses a centos base).
|
||||
centos:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
container:
|
||||
- "centos:7" # GCC 4.8
|
||||
- "almalinux:8"
|
||||
- "almalinux:9"
|
||||
|
||||
@ -644,18 +672,13 @@ jobs:
|
||||
steps:
|
||||
- name: Latest actions/checkout
|
||||
uses: actions/checkout@v4
|
||||
if: matrix.container != 'centos:7'
|
||||
|
||||
- name: Pin actions/checkout as required for centos:7
|
||||
uses: actions/checkout@v3
|
||||
if: matrix.container == 'centos:7'
|
||||
- name: Add Python 3.8
|
||||
if: matrix.container == 'almalinux:8'
|
||||
run: dnf update -y && dnf install -y python38-devel gcc-c++ make git
|
||||
|
||||
- name: Add Python 3 (RHEL 7)
|
||||
if: matrix.container == 'centos:7'
|
||||
run: yum update -y && yum install -y python3-devel gcc-c++ make git
|
||||
|
||||
- name: Add Python 3 (RHEL 8+)
|
||||
if: matrix.container != 'centos:7'
|
||||
- name: Add Python 3 (default)
|
||||
if: matrix.container != 'almalinux:8'
|
||||
run: dnf update -y && dnf install -y python3-devel gcc-c++ make git
|
||||
|
||||
- name: Update pip
|
||||
@ -778,17 +801,25 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python:
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8
|
||||
- 3.9
|
||||
- '3.7'
|
||||
- '3.8'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
- '3.11'
|
||||
- '3.12'
|
||||
|
||||
include:
|
||||
- python: 3.9
|
||||
- python: '3.12'
|
||||
args: -DCMAKE_CXX_STANDARD=20
|
||||
- python: 3.8
|
||||
- python: '3.11'
|
||||
args: -DCMAKE_CXX_STANDARD=20
|
||||
- python: '3.10'
|
||||
args: -DCMAKE_CXX_STANDARD=20
|
||||
- python: '3.9'
|
||||
args: -DCMAKE_CXX_STANDARD=20
|
||||
- python: '3.8'
|
||||
args: -DCMAKE_CXX_STANDARD=17
|
||||
- python: 3.7
|
||||
- python: '3.7'
|
||||
args: -DCMAKE_CXX_STANDARD=14
|
||||
|
||||
|
||||
@ -972,7 +1003,6 @@ jobs:
|
||||
mingw-w64-${{matrix.env}}-cmake
|
||||
mingw-w64-${{matrix.env}}-make
|
||||
mingw-w64-${{matrix.env}}-python-pytest
|
||||
mingw-w64-${{matrix.env}}-eigen3
|
||||
mingw-w64-${{matrix.env}}-boost
|
||||
mingw-w64-${{matrix.env}}-catch
|
||||
|
||||
@ -983,6 +1013,7 @@ jobs:
|
||||
install: >-
|
||||
git
|
||||
mingw-w64-${{matrix.env}}-python-scipy
|
||||
mingw-w64-${{matrix.env}}-eigen3
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
@ -1078,7 +1109,7 @@ jobs:
|
||||
uses: jwlawson/actions-setup-cmake@v2.0
|
||||
|
||||
- name: Install ninja-build tool
|
||||
uses: seanmiddleditch/gha-setup-ninja@v4
|
||||
uses: seanmiddleditch/gha-setup-ninja@v5
|
||||
|
||||
- name: Run pip installs
|
||||
run: |
|
||||
@ -1118,8 +1149,8 @@ jobs:
|
||||
run: git clean -fdx
|
||||
|
||||
macos_brew_install_llvm:
|
||||
name: "macos-latest • brew install llvm"
|
||||
runs-on: macos-latest
|
||||
name: "macos-13 • brew install llvm"
|
||||
runs-on: macos-13
|
||||
|
||||
env:
|
||||
# https://apple.stackexchange.com/questions/227026/how-to-install-recent-clang-with-homebrew
|
||||
|
6
.github/workflows/configure.yml
vendored
6
.github/workflows/configure.yml
vendored
@ -24,7 +24,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
runs-on: [ubuntu-20.04, macos-latest, windows-latest]
|
||||
runs-on: [ubuntu-20.04, macos-13, windows-latest]
|
||||
arch: [x64]
|
||||
cmake: ["3.26"]
|
||||
|
||||
@ -35,9 +35,9 @@ jobs:
|
||||
|
||||
- runs-on: ubuntu-20.04
|
||||
arch: x64
|
||||
cmake: "3.27"
|
||||
cmake: "3.29"
|
||||
|
||||
- runs-on: macos-latest
|
||||
- runs-on: macos-13
|
||||
arch: x64
|
||||
cmake: "3.7"
|
||||
|
||||
|
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
|
||||
- uses: actions/labeler@v4
|
||||
- uses: actions/labeler@v5
|
||||
if: >
|
||||
github.event.pull_request.merged == true &&
|
||||
!startsWith(github.event.pull_request.title, 'chore(deps):') &&
|
||||
|
25
.github/workflows/pip.yml
vendored
25
.github/workflows/pip.yml
vendored
@ -21,19 +21,18 @@ env:
|
||||
|
||||
jobs:
|
||||
# This builds the sdists and wheels and makes sure the files are exactly as
|
||||
# expected. Using Windows and Python 3.6, since that is often the most
|
||||
# challenging matrix element.
|
||||
# expected.
|
||||
test-packaging:
|
||||
name: 🐍 3.6 • 📦 tests • windows-latest
|
||||
name: 🐍 3.8 • 📦 tests • windows-latest
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup 🐍 3.6
|
||||
- name: Setup 🐍 3.8
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.6
|
||||
python-version: 3.8
|
||||
|
||||
- name: Prepare env
|
||||
run: |
|
||||
@ -92,23 +91,27 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'release' && github.event.action == 'published'
|
||||
needs: [packaging]
|
||||
environment: pypi
|
||||
permissions:
|
||||
id-token: write
|
||||
attestations: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
# Downloads all to directories matching the artifact names
|
||||
- uses: actions/download-artifact@v4
|
||||
|
||||
- name: Generate artifact attestation for sdist and wheel
|
||||
uses: actions/attest-build-provenance@173725a1209d09b31f9d30a3890cf2757ebbff0d # v1.1.2
|
||||
with:
|
||||
subject-path: "*/pybind11*"
|
||||
|
||||
- name: Publish standard package
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.pypi_password }}
|
||||
packages-dir: standard/
|
||||
|
||||
- name: Publish global package
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
password: ${{ secrets.pypi_password_global }}
|
||||
packages-dir: global/
|
||||
|
@ -25,14 +25,14 @@ repos:
|
||||
|
||||
# Clang format the codebase automatically
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: "v17.0.6"
|
||||
rev: "v18.1.5"
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c++, c, cuda]
|
||||
|
||||
# Ruff, the Python auto-correcting linter/formatter written in Rust
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.2.0
|
||||
rev: v0.4.7
|
||||
hooks:
|
||||
- id: ruff
|
||||
args: ["--fix", "--show-fixes"]
|
||||
@ -40,13 +40,13 @@ repos:
|
||||
|
||||
# Check static types with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: "v1.8.0"
|
||||
rev: "v1.10.0"
|
||||
hooks:
|
||||
- id: mypy
|
||||
args: []
|
||||
exclude: ^(tests|docs)/
|
||||
additional_dependencies:
|
||||
- markdown-it-py<3 # Drop this together with dropping Python 3.7 support.
|
||||
- markdown-it-py
|
||||
- nox
|
||||
- rich
|
||||
- types-setuptools
|
||||
@ -62,7 +62,7 @@ repos:
|
||||
|
||||
# Standard hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: "v4.5.0"
|
||||
rev: "v4.6.0"
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@ -78,7 +78,7 @@ repos:
|
||||
- id: trailing-whitespace
|
||||
|
||||
# Also code format the docs
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
- repo: https://github.com/adamchainz/blacken-docs
|
||||
rev: "1.16.0"
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
@ -87,13 +87,13 @@ repos:
|
||||
|
||||
# Changes tabs to spaces
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: "v1.5.4"
|
||||
rev: "v1.5.5"
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
|
||||
# Avoid directional quotes
|
||||
- repo: https://github.com/sirosen/texthooks
|
||||
rev: "0.6.4"
|
||||
rev: "0.6.6"
|
||||
hooks:
|
||||
- id: fix-ligatures
|
||||
- id: fix-smartquotes
|
||||
@ -119,15 +119,15 @@ repos:
|
||||
# Use tools/codespell_ignore_lines_from_errors.py
|
||||
# to rebuild .codespell-ignore-lines
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: "v2.2.6"
|
||||
rev: "v2.3.0"
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ".supp$"
|
||||
args: ["-x.codespell-ignore-lines", "-Lccompiler"]
|
||||
args: ["-x.codespell-ignore-lines", "-Lccompiler,intstruct"]
|
||||
|
||||
# Check for common shell mistakes
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: "v0.9.0.6"
|
||||
rev: "v0.10.0.1"
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
@ -142,13 +142,14 @@ repos:
|
||||
|
||||
# PyLint has native support - not always usable, but works for us
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: "v3.0.3"
|
||||
rev: "v3.2.2"
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^pybind11
|
||||
|
||||
# Check schemas on some of our YAML files
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.28.0
|
||||
rev: 0.28.4
|
||||
hooks:
|
||||
- id: check-readthedocs
|
||||
- id: check-github-workflows
|
||||
|
@ -12,13 +12,13 @@ endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
if(_pybind11_cmp0148)
|
||||
@ -116,6 +116,7 @@ option(PYBIND11_NUMPY_1_ONLY
|
||||
set(PYBIND11_INTERNALS_VERSION
|
||||
""
|
||||
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
|
||||
option(PYBIND11_USE_CROSSCOMPILING "Respect CMAKE_CROSSCOMPILING" OFF)
|
||||
|
||||
if(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
|
||||
add_compile_definitions(PYBIND11_DISABLE_HANDLE_TYPE_NAME_DEFAULT_IMPLEMENTATION)
|
||||
@ -299,6 +300,7 @@ if(PYBIND11_INSTALL)
|
||||
tools/pybind11Common.cmake
|
||||
tools/pybind11Tools.cmake
|
||||
tools/pybind11NewTools.cmake
|
||||
tools/pybind11GuessPythonExtSuffix.cmake
|
||||
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
if(NOT PYBIND11_EXPORT_NAME)
|
||||
|
@ -34,7 +34,7 @@ dependency.
|
||||
Think of this library as a tiny self-contained version of Boost.Python
|
||||
with everything stripped away that isn't relevant for binding
|
||||
generation. Without comments, the core header files only require ~4K
|
||||
lines of code and depend on Python (3.6+, or PyPy) and the C++
|
||||
lines of code and depend on Python (3.7+, or PyPy) and the C++
|
||||
standard library. This compact implementation was possible thanks to
|
||||
some C++11 language features (specifically: tuples, lambda functions and
|
||||
variadic templates). Since its creation, this library has grown beyond
|
||||
@ -79,7 +79,7 @@ Goodies
|
||||
In addition to the core functionality, pybind11 provides some extra
|
||||
goodies:
|
||||
|
||||
- Python 3.6+, and PyPy3 7.3 are supported with an implementation-agnostic
|
||||
- Python 3.7+, and PyPy3 7.3 are supported with an implementation-agnostic
|
||||
interface (pybind11 2.9 was the last version to support Python 2 and 3.5).
|
||||
|
||||
- It is possible to bind C++11 lambda functions with captured
|
||||
|
@ -18,7 +18,7 @@ information, see :doc:`/compiling`.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.27)
|
||||
cmake_minimum_required(VERSION 3.5...3.29)
|
||||
project(example)
|
||||
|
||||
find_package(pybind11 REQUIRED) # or `add_subdirectory(pybind11)`
|
||||
|
@ -378,8 +378,6 @@ uses of ``py::array``:
|
||||
|
||||
- ``.itemsize()`` returns the size of an item in bytes, i.e. ``sizeof(T)``.
|
||||
|
||||
- ``.ndim()`` returns the number of dimensions.
|
||||
|
||||
- ``.shape(n)`` returns the size of dimension ``n``
|
||||
|
||||
- ``.size()`` returns the total number of elements (i.e. the product of the shapes).
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime as dt
|
||||
import os
|
||||
import random
|
||||
|
@ -15,7 +15,108 @@ IN DEVELOPMENT
|
||||
|
||||
Changes will be summarized here periodically.
|
||||
|
||||
Version 2.12.0 (March 27, 2025)
|
||||
Version 2.13.0 (June 25, 2024)
|
||||
------------------------------
|
||||
|
||||
New Features:
|
||||
|
||||
* Support free-threaded CPython (3.13t). Add ``py::mod_gil_not_used()`` tag to
|
||||
indicate if a module supports running with the GIL disabled.
|
||||
`#5148 <https://github.com/pybind/pybind11/pull/5148>`_
|
||||
|
||||
* Support for Python 3.6 was removed. (Official end-of-life: 2021-12-23).
|
||||
`#5177 <https://github.com/pybind/pybind11/pull/5177>`_
|
||||
|
||||
* ``py::list`` gained a ``.clear()`` method.
|
||||
`#5153 <https://github.com/pybind/pybind11/pull/5153>`_
|
||||
|
||||
|
||||
.. feat(types)
|
||||
|
||||
* Support for ``Union``, ``Optional``, ``type[T]``, ``typing.TypeGuard``,
|
||||
``typing.TypeIs``, ``typing.Never``, ``typing.NoReturn`` and
|
||||
``typing.Literal`` was added to ``pybind11/typing.h``.
|
||||
`#5166 <https://github.com/pybind/pybind11/pull/5166>`_
|
||||
`#5165 <https://github.com/pybind/pybind11/pull/5165>`_
|
||||
`#5194 <https://github.com/pybind/pybind11/pull/5194>`_
|
||||
`#5193 <https://github.com/pybind/pybind11/pull/5193>`_
|
||||
`#5192 <https://github.com/pybind/pybind11/pull/5192>`_
|
||||
|
||||
|
||||
.. feat(cmake)
|
||||
|
||||
* In CMake, if ``PYBIND11_USE_CROSSCOMPILING`` is enabled, then
|
||||
``CMAKE_CROSSCOMPILING`` will be respected and will keep pybind11 from
|
||||
accessing the interpreter during configuration. Several CMake variables will
|
||||
be required in this case, but can be deduced from the environment variable
|
||||
``SETUPTOOLS_EXT_SUFFIX``. The default (currently ``OFF``) may be changed in
|
||||
the future.
|
||||
`#5083 <https://github.com/pybind/pybind11/pull/5083>`_
|
||||
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* A refcount bug (leading to heap-use-after-free) involving trampoline
|
||||
functions with ``PyObject *`` return type was fixed.
|
||||
`#5156 <https://github.com/pybind/pybind11/pull/5156>`_
|
||||
|
||||
* Return ``py::ssize_t`` from ``.ref_count()`` instead of ``int``.
|
||||
`#5139 <https://github.com/pybind/pybind11/pull/5139>`_
|
||||
|
||||
* A subtle bug involving C++ types with unusual ``operator&`` overrides
|
||||
was fixed.
|
||||
`#5189 <https://github.com/pybind/pybind11/pull/5189>`_
|
||||
|
||||
* Support Python 3.13 with minor fix, add to CI.
|
||||
`#5127 <https://github.com/pybind/pybind11/pull/5127>`_
|
||||
|
||||
|
||||
.. fix(cmake)
|
||||
|
||||
* Fix mistake affecting old cmake and old boost.
|
||||
`#5149 <https://github.com/pybind/pybind11/pull/5149>`_
|
||||
|
||||
|
||||
Documentation:
|
||||
|
||||
* Build docs updated to feature scikit-build-core and meson-python, and updated
|
||||
setuptools instructions.
|
||||
`#5168 <https://github.com/pybind/pybind11/pull/5168>`_
|
||||
|
||||
|
||||
Tests:
|
||||
|
||||
* Avoid immortal objects in tests.
|
||||
`#5150 <https://github.com/pybind/pybind11/pull/5150>`_
|
||||
|
||||
|
||||
CI:
|
||||
|
||||
* Compile against Python 3.13t in CI.
|
||||
|
||||
* Use ``macos-13`` (Intel) for CI jobs for now (will drop Python 3.7 soon).
|
||||
`#5109 <https://github.com/pybind/pybind11/pull/5109>`_
|
||||
|
||||
* Releases now have artifact attestations, visible at
|
||||
https://github.com/pybind/pybind11/attestations.
|
||||
`#5196 <https://github.com/pybind/pybind11/pull/5196>`_
|
||||
|
||||
Other:
|
||||
|
||||
* Some cleanup in preparation for 3.13 support.
|
||||
`#5137 <https://github.com/pybind/pybind11/pull/5137>`_
|
||||
|
||||
* Avoid a warning by ensuring an iterator end check is included in release mode.
|
||||
`#5129 <https://github.com/pybind/pybind11/pull/5129>`_
|
||||
|
||||
* Bump max cmake to 3.29.
|
||||
`#5075 <https://github.com/pybind/pybind11/pull/5075>`_
|
||||
|
||||
* Update docs and noxfile.
|
||||
`#5071 <https://github.com/pybind/pybind11/pull/5071>`_
|
||||
|
||||
|
||||
Version 2.12.0 (March 27, 2024)
|
||||
-------------------------------
|
||||
|
||||
New Features:
|
||||
|
@ -3,15 +3,123 @@
|
||||
Build systems
|
||||
#############
|
||||
|
||||
For an overview of Python packaging including compiled packaging with a pybind11
|
||||
example, along with a cookiecutter that includes several pybind11 options, see
|
||||
the `Scientific Python Development Guide`_.
|
||||
|
||||
.. _Scientific Python Development Guide: https://learn.scientific-python.org/development/guides/packaging-compiled/
|
||||
|
||||
.. scikit-build-core:
|
||||
|
||||
Modules with CMake
|
||||
==================
|
||||
|
||||
A Python extension module can be created with just a few lines of code:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.15...3.29)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
set(PYBIND11_FINDPYTHON ON)
|
||||
find_package(pybind11 CONFIG REQUIRED)
|
||||
|
||||
pybind11_add_module(example example.cpp)
|
||||
install(TARGET example DESTINATION .)
|
||||
|
||||
(You use the ``add_subdirectory`` instead, see the example in :ref:`cmake`.) In
|
||||
this example, the code is located in a file named :file:`example.cpp`. Either
|
||||
method will import the pybind11 project which provides the
|
||||
``pybind11_add_module`` function. It will take care of all the details needed
|
||||
to build a Python extension module on any platform.
|
||||
|
||||
To build with pip, build, cibuildwheel, uv, or other Python tools, you can
|
||||
add a ``pyproject.toml`` file like this:
|
||||
|
||||
.. code-block:: toml
|
||||
|
||||
[build-system]
|
||||
requires = ["scikit-build-core", "pybind11"]
|
||||
build-backend = "scikit_build_core.build"
|
||||
|
||||
[project]
|
||||
name = "example"
|
||||
version = "0.1.0"
|
||||
|
||||
You don't need setuptools files like ``MANIFEST.in``, ``setup.py``, or
|
||||
``setup.cfg``, as this is not setuptools. See `scikit-build-core`_ for details.
|
||||
For projects you plan to upload to PyPI, be sure to fill out the ``[project]``
|
||||
table with other important metadata as well (see `Writing pyproject.toml`_).
|
||||
|
||||
A working sample project can be found in the [scikit_build_example]_
|
||||
repository. An older and harder-to-maintain method is in [cmake_example]_. More
|
||||
details about our cmake support can be found below in :ref:`cmake`.
|
||||
|
||||
.. _scikit-build-core: https://scikit-build-core.readthedocs.io
|
||||
|
||||
.. [scikit_build_example] https://github.com/pybind/scikit_build_example
|
||||
|
||||
.. [cmake_example] https://github.com/pybind/cmake_example
|
||||
|
||||
.. _modules-meson-python:
|
||||
|
||||
Modules with meson-python
|
||||
=========================
|
||||
|
||||
You can also build a package with `Meson`_ using `meson-python`_, if you prefer
|
||||
that. Your ``meson.build`` file would look something like this:
|
||||
|
||||
.. _meson-example:
|
||||
|
||||
.. code-block:: meson
|
||||
|
||||
project(
|
||||
'example',
|
||||
'cpp',
|
||||
version: '0.1.0',
|
||||
default_options: [
|
||||
'cpp_std=c++11',
|
||||
],
|
||||
)
|
||||
|
||||
py = import('python').find_installation(pure: false)
|
||||
pybind11_dep = dependency('pybind11')
|
||||
|
||||
py.extension_module('example',
|
||||
'example.cpp',
|
||||
install: true,
|
||||
dependencies : [pybind11_dep],
|
||||
)
|
||||
|
||||
|
||||
And you would need a ``pyproject.toml`` file like this:
|
||||
|
||||
.. code-block:: toml
|
||||
|
||||
[build-system]
|
||||
requires = ["meson-python", "pybind11"]
|
||||
build-backend = "mesonpy"
|
||||
|
||||
Meson-python *requires* your project to be in git (or mercurial) as it uses it
|
||||
for the SDist creation. For projects you plan to upload to PyPI, be sure to fill out the
|
||||
``[project]`` table as well (see `Writing pyproject.toml`_).
|
||||
|
||||
|
||||
.. _Writing pyproject.toml: https://packaging.python.org/en/latest/guides/writing-pyproject-toml
|
||||
|
||||
.. _meson: https://mesonbuild.com
|
||||
|
||||
.. _meson-python: https://meson-python.readthedocs.io/en/latest
|
||||
|
||||
.. _build-setuptools:
|
||||
|
||||
Building with setuptools
|
||||
========================
|
||||
Modules with setuptools
|
||||
=======================
|
||||
|
||||
For projects on PyPI, building with setuptools is the way to go. Sylvain Corlay
|
||||
has kindly provided an example project which shows how to set up everything,
|
||||
including automatic generation of documentation using Sphinx. Please refer to
|
||||
the [python_example]_ repository.
|
||||
For projects on PyPI, a historically popular option is setuptools. Sylvain
|
||||
Corlay has kindly provided an example project which shows how to set up
|
||||
everything, including automatic generation of documentation using Sphinx.
|
||||
Please refer to the [python_example]_ repository.
|
||||
|
||||
.. [python_example] https://github.com/pybind/python_example
|
||||
|
||||
@ -21,11 +129,11 @@ To use pybind11 inside your ``setup.py``, you have to have some system to
|
||||
ensure that ``pybind11`` is installed when you build your package. There are
|
||||
four possible ways to do this, and pybind11 supports all four: You can ask all
|
||||
users to install pybind11 beforehand (bad), you can use
|
||||
:ref:`setup_helpers-pep518` (good, but very new and requires Pip 10),
|
||||
:ref:`setup_helpers-setup_requires` (discouraged by Python packagers now that
|
||||
PEP 518 is available, but it still works everywhere), or you can
|
||||
:ref:`setup_helpers-copy-manually` (always works but you have to manually sync
|
||||
your copy to get updates).
|
||||
:ref:`setup_helpers-pep518` (good), ``setup_requires=`` (discouraged), or you
|
||||
can :ref:`setup_helpers-copy-manually` (works but you have to manually sync
|
||||
your copy to get updates). Third party packagers like conda-forge generally
|
||||
strongly prefer the ``pyproject.toml`` method, as it gives them control over
|
||||
the ``pybind11`` version, and they may apply patches, etc.
|
||||
|
||||
An example of a ``setup.py`` using pybind11's helpers:
|
||||
|
||||
@ -122,70 +230,41 @@ version number that includes the number of commits since your last tag and a
|
||||
hash for a dirty directory. Another way to force a rebuild is purge your cache
|
||||
or use Pip's ``--no-cache-dir`` option.
|
||||
|
||||
You also need a ``MANIFEST.in`` file to include all relevant files so that you
|
||||
can make an SDist. If you use `pypa-build`_, that will build an SDist then a
|
||||
wheel from that SDist by default, so you can look inside those files (wheels
|
||||
are just zip files with a ``.whl`` extension) to make sure you aren't missing
|
||||
files. `check-manifest`_ (setuptools specific) or `check-sdist`_ (general) are
|
||||
CLI tools that can compare the SDist contents with your source control.
|
||||
|
||||
.. [Ccache] https://ccache.dev
|
||||
|
||||
.. [setuptools_scm] https://github.com/pypa/setuptools_scm
|
||||
|
||||
.. _setup_helpers-pep518:
|
||||
|
||||
PEP 518 requirements (Pip 10+ required)
|
||||
---------------------------------------
|
||||
Build requirements
|
||||
------------------
|
||||
|
||||
If you use `PEP 518's <https://www.python.org/dev/peps/pep-0518/>`_
|
||||
``pyproject.toml`` file, you can ensure that ``pybind11`` is available during
|
||||
the compilation of your project. When this file exists, Pip will make a new
|
||||
virtual environment, download just the packages listed here in ``requires=``,
|
||||
and build a wheel (binary Python package). It will then throw away the
|
||||
environment, and install your wheel.
|
||||
With a ``pyproject.toml`` file, you can ensure that ``pybind11`` is available
|
||||
during the compilation of your project. When this file exists, Pip will make a
|
||||
new virtual environment, download just the packages listed here in
|
||||
``requires=``, and build a wheel (binary Python package). It will then throw
|
||||
away the environment, and install your wheel.
|
||||
|
||||
Your ``pyproject.toml`` file will likely look something like this:
|
||||
|
||||
.. code-block:: toml
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=42", "pybind11>=2.6.1"]
|
||||
requires = ["setuptools", "pybind11"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
.. note::
|
||||
|
||||
The main drawback to this method is that a `PEP 517`_ compliant build tool,
|
||||
such as Pip 10+, is required for this approach to work; older versions of
|
||||
Pip completely ignore this file. If you distribute binaries (called wheels
|
||||
in Python) using something like `cibuildwheel`_, remember that ``setup.py``
|
||||
and ``pyproject.toml`` are not even contained in the wheel, so this high
|
||||
Pip requirement is only for source builds, and will not affect users of
|
||||
your binary wheels. If you are building SDists and wheels, then
|
||||
`pypa-build`_ is the recommended official tool.
|
||||
|
||||
.. _PEP 517: https://www.python.org/dev/peps/pep-0517/
|
||||
.. _cibuildwheel: https://cibuildwheel.readthedocs.io
|
||||
.. _pypa-build: https://pypa-build.readthedocs.io/en/latest/
|
||||
|
||||
.. _setup_helpers-setup_requires:
|
||||
|
||||
Classic ``setup_requires``
|
||||
--------------------------
|
||||
|
||||
If you want to support old versions of Pip with the classic
|
||||
``setup_requires=["pybind11"]`` keyword argument to setup, which triggers a
|
||||
two-phase ``setup.py`` run, then you will need to use something like this to
|
||||
ensure the first pass works (which has not yet installed the ``setup_requires``
|
||||
packages, since it can't install something it does not know about):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
from pybind11.setup_helpers import Pybind11Extension
|
||||
except ImportError:
|
||||
from setuptools import Extension as Pybind11Extension
|
||||
|
||||
|
||||
It doesn't matter that the Extension class is not the enhanced subclass for the
|
||||
first pass run; and the second pass will have the ``setup_requires``
|
||||
requirements.
|
||||
|
||||
This is obviously more of a hack than the PEP 518 method, but it supports
|
||||
ancient versions of Pip.
|
||||
.. _cibuildwheel: https://cibuildwheel.pypa.io
|
||||
.. _pypa-build: https://build.pypa.io/en/latest/
|
||||
.. _check-manifest: https://pypi.io/project/check-manifest
|
||||
.. _check-sdist: https://pypi.io/project/check-sdist
|
||||
|
||||
.. _setup_helpers-copy-manually:
|
||||
|
||||
@ -231,32 +310,22 @@ the C++ source file. Python is then able to find the module and load it.
|
||||
|
||||
.. [cppimport] https://github.com/tbenthompson/cppimport
|
||||
|
||||
|
||||
|
||||
.. _cmake:
|
||||
|
||||
Building with CMake
|
||||
===================
|
||||
|
||||
For C++ codebases that have an existing CMake-based build system, a Python
|
||||
extension module can be created with just a few lines of code:
|
||||
extension module can be created with just a few lines of code, as seen above in
|
||||
the module section. Pybind11 currently supports a lower minimum if you don't
|
||||
use the modern FindPython, though be aware that CMake 3.27 removed the old
|
||||
mechanism, so pybind11 will automatically switch if the old mechanism is not
|
||||
available. Please opt into the new mechanism if at all possible. Our default
|
||||
may change in future versions. This is the minimum required:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.27)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(pybind11)
|
||||
pybind11_add_module(example example.cpp)
|
||||
|
||||
This assumes that the pybind11 repository is located in a subdirectory named
|
||||
:file:`pybind11` and that the code is located in a file named :file:`example.cpp`.
|
||||
The CMake command ``add_subdirectory`` will import the pybind11 project which
|
||||
provides the ``pybind11_add_module`` function. It will take care of all the
|
||||
details needed to build a Python extension module on any platform.
|
||||
|
||||
A working sample project, including a way to invoke CMake from :file:`setup.py` for
|
||||
PyPI integration, can be found in the [cmake_example]_ repository.
|
||||
|
||||
.. [cmake_example] https://github.com/pybind/cmake_example
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
CMake 3.4+ is required.
|
||||
@ -264,6 +333,7 @@ PyPI integration, can be found in the [cmake_example]_ repository.
|
||||
.. versionchanged:: 2.11
|
||||
CMake 3.5+ is required.
|
||||
|
||||
|
||||
Further information can be found at :doc:`cmake/index`.
|
||||
|
||||
pybind11_add_module
|
||||
@ -356,7 +426,7 @@ with ``PYTHON_EXECUTABLE``. For example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cmake -DPYBIND11_PYTHON_VERSION=3.6 ..
|
||||
cmake -DPYBIND11_PYTHON_VERSION=3.7 ..
|
||||
|
||||
# Another method:
|
||||
cmake -DPYTHON_EXECUTABLE=/path/to/python ..
|
||||
@ -423,7 +493,7 @@ existing targets instead:
|
||||
cmake_minimum_required(VERSION 3.15...3.22)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
find_package(Python 3.6 COMPONENTS Interpreter Development REQUIRED)
|
||||
find_package(Python 3.7 COMPONENTS Interpreter Development REQUIRED)
|
||||
find_package(pybind11 CONFIG REQUIRED)
|
||||
# or add_subdirectory(pybind11)
|
||||
|
||||
@ -498,7 +568,7 @@ You can use these targets to build complex applications. For example, the
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.27)
|
||||
cmake_minimum_required(VERSION 3.5...3.29)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
|
||||
@ -556,7 +626,7 @@ information about usage in C++, see :doc:`/advanced/embedding`.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.5...3.27)
|
||||
cmake_minimum_required(VERSION 3.5...3.29)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
find_package(pybind11 REQUIRED) # or add_subdirectory(pybind11)
|
||||
@ -616,6 +686,13 @@ Building with Bazel
|
||||
You can build with the Bazel build system using the `pybind11_bazel
|
||||
<https://github.com/pybind/pybind11_bazel>`_ repository.
|
||||
|
||||
Building with Meson
|
||||
===================
|
||||
|
||||
You can use Meson, which has support for ``pybind11`` as a dependency (internally
|
||||
relying on our ``pkg-config`` support). See the :ref:`module example above <meson-example>`.
|
||||
|
||||
|
||||
Generating binding code automatically
|
||||
=====================================
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import re
|
||||
@ -81,7 +82,7 @@ version = loc["__version__"]
|
||||
#
|
||||
# This is also used if you do content translation via gettext catalogs.
|
||||
# Usually you set "language" from the command line for these cases.
|
||||
language = None
|
||||
language = "en"
|
||||
|
||||
# There are two options for replacing |today|: either, you set today to some
|
||||
# non-false value, then it is used:
|
||||
|
6
docs/requirements.in
Normal file
6
docs/requirements.in
Normal file
@ -0,0 +1,6 @@
|
||||
breathe
|
||||
furo
|
||||
sphinx
|
||||
sphinx-copybutton
|
||||
sphinxcontrib-moderncmakedomain
|
||||
sphinxcontrib-svg2pdfconverter
|
@ -1,6 +1,275 @@
|
||||
breathe==4.34.0
|
||||
furo==2022.6.21
|
||||
sphinx==5.0.2
|
||||
sphinx-copybutton==0.5.0
|
||||
sphinxcontrib-moderncmakedomain==3.21.4
|
||||
sphinxcontrib-svg2pdfconverter==1.2.0
|
||||
# This file was autogenerated by uv via the following command:
|
||||
# uv pip compile --generate-hashes docs/requirements.in -o docs/requirements.txt
|
||||
alabaster==0.7.16 \
|
||||
--hash=sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65 \
|
||||
--hash=sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92
|
||||
# via sphinx
|
||||
babel==2.14.0 \
|
||||
--hash=sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363 \
|
||||
--hash=sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287
|
||||
# via sphinx
|
||||
beautifulsoup4==4.12.3 \
|
||||
--hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \
|
||||
--hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed
|
||||
# via furo
|
||||
breathe==4.35.0 \
|
||||
--hash=sha256:5165541c3c67b6c7adde8b3ecfe895c6f7844783c4076b6d8d287e4f33d62386 \
|
||||
--hash=sha256:52c581f42ca4310737f9e435e3851c3d1f15446205a85fbc272f1f97ed74f5be
|
||||
# via -r requirements.in
|
||||
certifi==2024.2.2 \
|
||||
--hash=sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f \
|
||||
--hash=sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1
|
||||
# via requests
|
||||
charset-normalizer==3.3.2 \
|
||||
--hash=sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027 \
|
||||
--hash=sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087 \
|
||||
--hash=sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786 \
|
||||
--hash=sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8 \
|
||||
--hash=sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09 \
|
||||
--hash=sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185 \
|
||||
--hash=sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574 \
|
||||
--hash=sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e \
|
||||
--hash=sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519 \
|
||||
--hash=sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898 \
|
||||
--hash=sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269 \
|
||||
--hash=sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3 \
|
||||
--hash=sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f \
|
||||
--hash=sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6 \
|
||||
--hash=sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8 \
|
||||
--hash=sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a \
|
||||
--hash=sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73 \
|
||||
--hash=sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc \
|
||||
--hash=sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714 \
|
||||
--hash=sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2 \
|
||||
--hash=sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc \
|
||||
--hash=sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce \
|
||||
--hash=sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d \
|
||||
--hash=sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e \
|
||||
--hash=sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6 \
|
||||
--hash=sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269 \
|
||||
--hash=sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96 \
|
||||
--hash=sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d \
|
||||
--hash=sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a \
|
||||
--hash=sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4 \
|
||||
--hash=sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77 \
|
||||
--hash=sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d \
|
||||
--hash=sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0 \
|
||||
--hash=sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed \
|
||||
--hash=sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068 \
|
||||
--hash=sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac \
|
||||
--hash=sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25 \
|
||||
--hash=sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8 \
|
||||
--hash=sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab \
|
||||
--hash=sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26 \
|
||||
--hash=sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2 \
|
||||
--hash=sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db \
|
||||
--hash=sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f \
|
||||
--hash=sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5 \
|
||||
--hash=sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99 \
|
||||
--hash=sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c \
|
||||
--hash=sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d \
|
||||
--hash=sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811 \
|
||||
--hash=sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa \
|
||||
--hash=sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a \
|
||||
--hash=sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03 \
|
||||
--hash=sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b \
|
||||
--hash=sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04 \
|
||||
--hash=sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c \
|
||||
--hash=sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001 \
|
||||
--hash=sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458 \
|
||||
--hash=sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389 \
|
||||
--hash=sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99 \
|
||||
--hash=sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985 \
|
||||
--hash=sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537 \
|
||||
--hash=sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238 \
|
||||
--hash=sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f \
|
||||
--hash=sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d \
|
||||
--hash=sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796 \
|
||||
--hash=sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a \
|
||||
--hash=sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143 \
|
||||
--hash=sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8 \
|
||||
--hash=sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c \
|
||||
--hash=sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5 \
|
||||
--hash=sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5 \
|
||||
--hash=sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711 \
|
||||
--hash=sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4 \
|
||||
--hash=sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6 \
|
||||
--hash=sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c \
|
||||
--hash=sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7 \
|
||||
--hash=sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4 \
|
||||
--hash=sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b \
|
||||
--hash=sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae \
|
||||
--hash=sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12 \
|
||||
--hash=sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c \
|
||||
--hash=sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae \
|
||||
--hash=sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8 \
|
||||
--hash=sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887 \
|
||||
--hash=sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b \
|
||||
--hash=sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4 \
|
||||
--hash=sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f \
|
||||
--hash=sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5 \
|
||||
--hash=sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33 \
|
||||
--hash=sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519 \
|
||||
--hash=sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561
|
||||
# via requests
|
||||
docutils==0.20.1 \
|
||||
--hash=sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6 \
|
||||
--hash=sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b
|
||||
# via
|
||||
# breathe
|
||||
# sphinx
|
||||
furo==2024.1.29 \
|
||||
--hash=sha256:3548be2cef45a32f8cdc0272d415fcb3e5fa6a0eb4ddfe21df3ecf1fe45a13cf \
|
||||
--hash=sha256:4d6b2fe3f10a6e36eb9cc24c1e7beb38d7a23fc7b3c382867503b7fcac8a1e02
|
||||
# via -r requirements.in
|
||||
idna==3.7 \
|
||||
--hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
|
||||
--hash=sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0
|
||||
# via requests
|
||||
imagesize==1.4.1 \
|
||||
--hash=sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b \
|
||||
--hash=sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a
|
||||
# via sphinx
|
||||
jinja2==3.1.4 \
|
||||
--hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
|
||||
--hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
|
||||
# via sphinx
|
||||
markupsafe==2.1.5 \
|
||||
--hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
|
||||
--hash=sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff \
|
||||
--hash=sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f \
|
||||
--hash=sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3 \
|
||||
--hash=sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532 \
|
||||
--hash=sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f \
|
||||
--hash=sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617 \
|
||||
--hash=sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df \
|
||||
--hash=sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4 \
|
||||
--hash=sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906 \
|
||||
--hash=sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f \
|
||||
--hash=sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4 \
|
||||
--hash=sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8 \
|
||||
--hash=sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371 \
|
||||
--hash=sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2 \
|
||||
--hash=sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465 \
|
||||
--hash=sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52 \
|
||||
--hash=sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6 \
|
||||
--hash=sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169 \
|
||||
--hash=sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad \
|
||||
--hash=sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2 \
|
||||
--hash=sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0 \
|
||||
--hash=sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029 \
|
||||
--hash=sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f \
|
||||
--hash=sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a \
|
||||
--hash=sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced \
|
||||
--hash=sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5 \
|
||||
--hash=sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c \
|
||||
--hash=sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf \
|
||||
--hash=sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9 \
|
||||
--hash=sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb \
|
||||
--hash=sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad \
|
||||
--hash=sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3 \
|
||||
--hash=sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1 \
|
||||
--hash=sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46 \
|
||||
--hash=sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc \
|
||||
--hash=sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a \
|
||||
--hash=sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee \
|
||||
--hash=sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900 \
|
||||
--hash=sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5 \
|
||||
--hash=sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea \
|
||||
--hash=sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f \
|
||||
--hash=sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5 \
|
||||
--hash=sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e \
|
||||
--hash=sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a \
|
||||
--hash=sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f \
|
||||
--hash=sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50 \
|
||||
--hash=sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a \
|
||||
--hash=sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b \
|
||||
--hash=sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4 \
|
||||
--hash=sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff \
|
||||
--hash=sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2 \
|
||||
--hash=sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46 \
|
||||
--hash=sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b \
|
||||
--hash=sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf \
|
||||
--hash=sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5 \
|
||||
--hash=sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5 \
|
||||
--hash=sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab \
|
||||
--hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
|
||||
--hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
|
||||
# via jinja2
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
# via sphinx
|
||||
pygments==2.17.2 \
|
||||
--hash=sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c \
|
||||
--hash=sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367
|
||||
# via
|
||||
# furo
|
||||
# sphinx
|
||||
requests==2.32.0 \
|
||||
--hash=sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5 \
|
||||
--hash=sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8
|
||||
# via sphinx
|
||||
snowballstemmer==2.2.0 \
|
||||
--hash=sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1 \
|
||||
--hash=sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a
|
||||
# via sphinx
|
||||
soupsieve==2.5 \
|
||||
--hash=sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690 \
|
||||
--hash=sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7
|
||||
# via beautifulsoup4
|
||||
sphinx==7.2.6 \
|
||||
--hash=sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560 \
|
||||
--hash=sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5
|
||||
# via
|
||||
# -r requirements.in
|
||||
# breathe
|
||||
# furo
|
||||
# sphinx-basic-ng
|
||||
# sphinx-copybutton
|
||||
# sphinxcontrib-moderncmakedomain
|
||||
# sphinxcontrib-svg2pdfconverter
|
||||
sphinx-basic-ng==1.0.0b2 \
|
||||
--hash=sha256:9ec55a47c90c8c002b5960c57492ec3021f5193cb26cebc2dc4ea226848651c9 \
|
||||
--hash=sha256:eb09aedbabfb650607e9b4b68c9d240b90b1e1be221d6ad71d61c52e29f7932b
|
||||
# via furo
|
||||
sphinx-copybutton==0.5.2 \
|
||||
--hash=sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd \
|
||||
--hash=sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e
|
||||
# via -r requirements.in
|
||||
sphinxcontrib-applehelp==1.0.8 \
|
||||
--hash=sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619 \
|
||||
--hash=sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4
|
||||
# via sphinx
|
||||
sphinxcontrib-devhelp==1.0.6 \
|
||||
--hash=sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f \
|
||||
--hash=sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3
|
||||
# via sphinx
|
||||
sphinxcontrib-htmlhelp==2.0.5 \
|
||||
--hash=sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015 \
|
||||
--hash=sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04
|
||||
# via sphinx
|
||||
sphinxcontrib-jsmath==1.0.1 \
|
||||
--hash=sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178 \
|
||||
--hash=sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8
|
||||
# via sphinx
|
||||
sphinxcontrib-moderncmakedomain==3.27.0 \
|
||||
--hash=sha256:51e259e91f58d17cc0fac9307fd40106aa59d5acaa741887903fc3660361d1a1 \
|
||||
--hash=sha256:70a73e0e7cff1b117074e968ccb7f72383ed0f572414df0e216cea06914de988
|
||||
# via -r requirements.in
|
||||
sphinxcontrib-qthelp==1.0.7 \
|
||||
--hash=sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6 \
|
||||
--hash=sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182
|
||||
# via sphinx
|
||||
sphinxcontrib-serializinghtml==1.1.10 \
|
||||
--hash=sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7 \
|
||||
--hash=sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f
|
||||
# via sphinx
|
||||
sphinxcontrib-svg2pdfconverter==1.2.2 \
|
||||
--hash=sha256:04ec767b55780a6b18d89cc1a8ada6d900c6efde9d1683abdb98a49b144465ca \
|
||||
--hash=sha256:80a55ca61f70eae93efc65f3814f2f177c86ba55934a9f6c5022f1778b62146b
|
||||
# via -r requirements.in
|
||||
urllib3==2.2.2 \
|
||||
--hash=sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472 \
|
||||
--hash=sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168
|
||||
# via requests
|
||||
|
@ -1339,13 +1339,24 @@ enable_if_t<!cast_is_temporary_value_reference<T>::value, T> cast_ref(object &&,
|
||||
// static_assert, even though if it's in dead code, so we provide a "trampoline" to pybind11::cast
|
||||
// that only does anything in cases where pybind11::cast is valid.
|
||||
template <typename T>
|
||||
enable_if_t<cast_is_temporary_value_reference<T>::value, T> cast_safe(object &&) {
|
||||
enable_if_t<cast_is_temporary_value_reference<T>::value
|
||||
&& !detail::is_same_ignoring_cvref<T, PyObject *>::value,
|
||||
T>
|
||||
cast_safe(object &&) {
|
||||
pybind11_fail("Internal error: cast_safe fallback invoked");
|
||||
}
|
||||
template <typename T>
|
||||
enable_if_t<std::is_void<T>::value, void> cast_safe(object &&) {}
|
||||
template <typename T>
|
||||
enable_if_t<detail::none_of<cast_is_temporary_value_reference<T>, std::is_void<T>>::value, T>
|
||||
enable_if_t<detail::is_same_ignoring_cvref<T, PyObject *>::value, PyObject *>
|
||||
cast_safe(object &&o) {
|
||||
return o.release().ptr();
|
||||
}
|
||||
template <typename T>
|
||||
enable_if_t<detail::none_of<cast_is_temporary_value_reference<T>,
|
||||
detail::is_same_ignoring_cvref<T, PyObject *>,
|
||||
std::is_void<T>>::value,
|
||||
T>
|
||||
cast_safe(object &&o) {
|
||||
return pybind11::cast<T>(std::move(o));
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, P
|
||||
|
||||
/// Cleanup the type-info for a pybind11-registered type.
|
||||
extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
|
||||
with_internals([obj](internals &internals) {
|
||||
auto *type = (PyTypeObject *) obj;
|
||||
auto &internals = get_internals();
|
||||
|
||||
// A pybind11-registered type will:
|
||||
// 1) be found in internals.registered_types_py
|
||||
@ -238,6 +238,7 @@ extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
|
||||
|
||||
delete tinfo;
|
||||
}
|
||||
});
|
||||
|
||||
PyType_Type.tp_dealloc(obj);
|
||||
}
|
||||
@ -310,19 +311,20 @@ inline void traverse_offset_bases(void *valueptr,
|
||||
}
|
||||
|
||||
inline bool register_instance_impl(void *ptr, instance *self) {
|
||||
get_internals().registered_instances.emplace(ptr, self);
|
||||
with_instance_map(ptr, [&](instance_map &instances) { instances.emplace(ptr, self); });
|
||||
return true; // unused, but gives the same signature as the deregister func
|
||||
}
|
||||
inline bool deregister_instance_impl(void *ptr, instance *self) {
|
||||
auto ®istered_instances = get_internals().registered_instances;
|
||||
auto range = registered_instances.equal_range(ptr);
|
||||
return with_instance_map(ptr, [&](instance_map &instances) {
|
||||
auto range = instances.equal_range(ptr);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (self == it->second) {
|
||||
registered_instances.erase(it);
|
||||
instances.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
inline void register_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||
@ -377,23 +379,32 @@ extern "C" inline int pybind11_object_init(PyObject *self, PyObject *, PyObject
|
||||
}
|
||||
|
||||
inline void add_patient(PyObject *nurse, PyObject *patient) {
|
||||
auto &internals = get_internals();
|
||||
auto *instance = reinterpret_cast<detail::instance *>(nurse);
|
||||
instance->has_patients = true;
|
||||
Py_INCREF(patient);
|
||||
internals.patients[nurse].push_back(patient);
|
||||
|
||||
with_internals([&](internals &internals) { internals.patients[nurse].push_back(patient); });
|
||||
}
|
||||
|
||||
inline void clear_patients(PyObject *self) {
|
||||
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||
auto &internals = get_internals();
|
||||
std::vector<PyObject *> patients;
|
||||
|
||||
with_internals([&](internals &internals) {
|
||||
auto pos = internals.patients.find(self);
|
||||
assert(pos != internals.patients.end());
|
||||
|
||||
if (pos == internals.patients.end()) {
|
||||
pybind11_fail(
|
||||
"FATAL: Internal consistency check failed: Invalid clear_patients() call.");
|
||||
}
|
||||
|
||||
// Clearing the patients can cause more Python code to run, which
|
||||
// can invalidate the iterator. Extract the vector of patients
|
||||
// from the unordered_map first.
|
||||
auto patients = std::move(pos->second);
|
||||
patients = std::move(pos->second);
|
||||
internals.patients.erase(pos);
|
||||
});
|
||||
|
||||
instance->has_patients = false;
|
||||
for (PyObject *&patient : patients) {
|
||||
Py_CLEAR(patient);
|
||||
@ -556,16 +567,8 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
|
||||
type->tp_traverse = pybind11_traverse;
|
||||
type->tp_clear = pybind11_clear;
|
||||
|
||||
static PyGetSetDef getset[] = {{
|
||||
#if PY_VERSION_HEX < 0x03070000
|
||||
const_cast<char *>("__dict__"),
|
||||
#else
|
||||
"__dict__",
|
||||
#endif
|
||||
PyObject_GenericGetDict,
|
||||
PyObject_GenericSetDict,
|
||||
nullptr,
|
||||
nullptr},
|
||||
static PyGetSetDef getset[]
|
||||
= {{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, nullptr, nullptr},
|
||||
{nullptr, nullptr, nullptr, nullptr, nullptr}};
|
||||
type->tp_getset = getset;
|
||||
}
|
||||
@ -658,10 +661,13 @@ inline PyObject *make_new_python_type(const type_record &rec) {
|
||||
|
||||
char *tp_doc = nullptr;
|
||||
if (rec.doc && options::show_user_defined_docstrings()) {
|
||||
/* Allocate memory for docstring (using PyObject_MALLOC, since
|
||||
Python will free this later on) */
|
||||
/* Allocate memory for docstring (Python will free this later on) */
|
||||
size_t size = std::strlen(rec.doc) + 1;
|
||||
#if PY_VERSION_HEX >= 0x030D0000
|
||||
tp_doc = (char *) PyMem_MALLOC(size);
|
||||
#else
|
||||
tp_doc = (char *) PyObject_MALLOC(size);
|
||||
#endif
|
||||
std::memcpy((void *) tp_doc, rec.doc, size);
|
||||
}
|
||||
|
||||
|
@ -10,12 +10,12 @@
|
||||
#pragma once
|
||||
|
||||
#define PYBIND11_VERSION_MAJOR 2
|
||||
#define PYBIND11_VERSION_MINOR 12
|
||||
#define PYBIND11_VERSION_MINOR 13
|
||||
#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 0x020C0000
|
||||
#define PYBIND11_VERSION_HEX 0x020D0000
|
||||
|
||||
// Define some generic pybind11 helper macros for warning management.
|
||||
//
|
||||
@ -272,9 +272,8 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
// Reminder: WITH_THREAD is always defined if PY_VERSION_HEX >= 0x03070000
|
||||
#if PY_VERSION_HEX < 0x03060000
|
||||
# error "PYTHON < 3.6 IS UNSUPPORTED. pybind11 v2.9 was the last to support Python 2 and 3.5."
|
||||
#if PY_VERSION_HEX < 0x03070000
|
||||
# error "PYTHON < 3.7 IS UNSUPPORTED. pybind11 v2.12 was the last to support Python 3.6."
|
||||
#endif
|
||||
#include <frameobject.h>
|
||||
#include <pythread.h>
|
||||
@ -464,7 +463,7 @@ PYBIND11_WARNING_POP
|
||||
});
|
||||
}
|
||||
\endrst */
|
||||
#define PYBIND11_MODULE(name, variable) \
|
||||
#define PYBIND11_MODULE(name, variable, ...) \
|
||||
static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name) \
|
||||
PYBIND11_MAYBE_UNUSED; \
|
||||
PYBIND11_MAYBE_UNUSED \
|
||||
@ -473,7 +472,10 @@ PYBIND11_WARNING_POP
|
||||
PYBIND11_CHECK_PYTHON_VERSION \
|
||||
PYBIND11_ENSURE_INTERNALS_READY \
|
||||
auto m = ::pybind11::module_::create_extension_module( \
|
||||
PYBIND11_TOSTRING(name), nullptr, &PYBIND11_CONCAT(pybind11_module_def_, name)); \
|
||||
PYBIND11_TOSTRING(name), \
|
||||
nullptr, \
|
||||
&PYBIND11_CONCAT(pybind11_module_def_, name), \
|
||||
##__VA_ARGS__); \
|
||||
try { \
|
||||
PYBIND11_CONCAT(pybind11_init_, name)(m); \
|
||||
return m.ptr(); \
|
||||
@ -925,8 +927,7 @@ using is_template_base_of
|
||||
= decltype(is_template_base_of_impl<Base>::check((intrinsic_t<T> *) nullptr));
|
||||
#else
|
||||
struct is_template_base_of
|
||||
: decltype(is_template_base_of_impl<Base>::check((intrinsic_t<T> *) nullptr)) {
|
||||
};
|
||||
: decltype(is_template_base_of_impl<Base>::check((intrinsic_t<T> *) nullptr)){};
|
||||
#endif
|
||||
|
||||
/// Check if T is an instantiation of the template `Class`. For example:
|
||||
@ -1108,14 +1109,14 @@ struct overload_cast_impl {
|
||||
}
|
||||
|
||||
template <typename Return, typename Class>
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...), std::false_type = {}) const noexcept
|
||||
-> decltype(pmf) {
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...),
|
||||
std::false_type = {}) const noexcept -> decltype(pmf) {
|
||||
return pmf;
|
||||
}
|
||||
|
||||
template <typename Return, typename Class>
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...) const, std::true_type) const noexcept
|
||||
-> decltype(pmf) {
|
||||
constexpr auto operator()(Return (Class::*pmf)(Args...) const,
|
||||
std::true_type) const noexcept -> decltype(pmf) {
|
||||
return pmf;
|
||||
}
|
||||
};
|
||||
|
@ -156,8 +156,9 @@ constexpr auto concat(const descr<N, Ts...> &d, const Args &...args) {
|
||||
}
|
||||
#else
|
||||
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...)) {
|
||||
constexpr auto concat(const descr<N, Ts...> &d,
|
||||
const Args &...args) -> decltype(std::declval<descr<N + 2, Ts...>>()
|
||||
+ concat(args...)) {
|
||||
return d + const_name(", ") + concat(args...);
|
||||
}
|
||||
#endif
|
||||
|
@ -11,13 +11,15 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if defined(WITH_THREAD) && defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
# include "../gil.h"
|
||||
#endif
|
||||
|
||||
#include "../pytypes.h"
|
||||
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
/// Tracks the `internals` and `type_info` ABI version independent of the main library version.
|
||||
///
|
||||
@ -62,10 +64,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
|
||||
|
||||
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
|
||||
// Thread Specific Storage (TSS) API.
|
||||
#if PY_VERSION_HEX >= 0x03070000
|
||||
// Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
|
||||
// `Py_LIMITED_API` anyway.
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
#if PYBIND11_INTERNALS_VERSION > 4
|
||||
# define PYBIND11_TLS_KEY_REF Py_tss_t &
|
||||
# if defined(__clang__)
|
||||
# define PYBIND11_TLS_KEY_INIT(var) \
|
||||
@ -89,7 +90,7 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value))
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr)
|
||||
# define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key))
|
||||
# else
|
||||
#else
|
||||
# define PYBIND11_TLS_KEY_REF Py_tss_t *
|
||||
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr;
|
||||
# define PYBIND11_TLS_KEY_CREATE(var) \
|
||||
@ -98,29 +99,6 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value))
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
|
||||
# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key)
|
||||
# endif
|
||||
#else
|
||||
// Usually an int but a long on Cygwin64 with Python 3.x
|
||||
# define PYBIND11_TLS_KEY_REF decltype(PyThread_create_key())
|
||||
# define PYBIND11_TLS_KEY_INIT(var) PYBIND11_TLS_KEY_REF var = 0;
|
||||
# define PYBIND11_TLS_KEY_CREATE(var) (((var) = PyThread_create_key()) != -1)
|
||||
# define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
|
||||
# if defined(PYPY_VERSION)
|
||||
// On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
|
||||
// the value if it has already been set. Instead, it must first be deleted and
|
||||
// then set again.
|
||||
inline void tls_replace_value(PYBIND11_TLS_KEY_REF key, void *value) {
|
||||
PyThread_delete_key_value(key);
|
||||
PyThread_set_key_value(key, value);
|
||||
}
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_delete_key_value(key)
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \
|
||||
::pybind11::detail::tls_replace_value((key), (value))
|
||||
# else
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_set_key_value((key), nullptr)
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_set_key_value((key), (value))
|
||||
# endif
|
||||
# define PYBIND11_TLS_FREE(key) (void) key
|
||||
#endif
|
||||
|
||||
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
|
||||
@ -168,15 +146,37 @@ struct override_hash {
|
||||
}
|
||||
};
|
||||
|
||||
using instance_map = std::unordered_multimap<const void *, instance *>;
|
||||
|
||||
// ignore: structure was padded due to alignment specifier
|
||||
PYBIND11_WARNING_PUSH
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4324)
|
||||
|
||||
// Instance map shards are used to reduce mutex contention in free-threaded Python.
|
||||
struct alignas(64) instance_map_shard {
|
||||
std::mutex mutex;
|
||||
instance_map registered_instances;
|
||||
};
|
||||
|
||||
PYBIND11_WARNING_POP
|
||||
|
||||
/// Internal data structure used to track registered instances and types.
|
||||
/// Whenever binary incompatible changes are made to this structure,
|
||||
/// `PYBIND11_INTERNALS_VERSION` must be incremented.
|
||||
struct internals {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
std::mutex mutex;
|
||||
#endif
|
||||
// std::type_index -> pybind11's type information
|
||||
type_map<type_info *> registered_types_cpp;
|
||||
// PyTypeObject* -> base type_info(s)
|
||||
std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py;
|
||||
std::unordered_multimap<const void *, instance *> registered_instances; // void * -> instance*
|
||||
#ifdef Py_GIL_DISABLED
|
||||
std::unique_ptr<instance_map_shard[]> instance_shards; // void * -> instance*
|
||||
size_t instance_shards_mask;
|
||||
#else
|
||||
instance_map registered_instances; // void * -> instance*
|
||||
#endif
|
||||
std::unordered_set<std::pair<const PyObject *, const char *>, override_hash>
|
||||
inactive_override_cache;
|
||||
type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
|
||||
@ -192,28 +192,27 @@ struct internals {
|
||||
PyTypeObject *static_property_type;
|
||||
PyTypeObject *default_metaclass;
|
||||
PyObject *instance_base;
|
||||
#if defined(WITH_THREAD)
|
||||
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
||||
PYBIND11_TLS_KEY_INIT(tstate)
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
#if PYBIND11_INTERNALS_VERSION > 4
|
||||
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||
# endif // PYBIND11_INTERNALS_VERSION > 4
|
||||
#endif // PYBIND11_INTERNALS_VERSION > 4
|
||||
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
|
||||
PyInterpreterState *istate = nullptr;
|
||||
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
#if PYBIND11_INTERNALS_VERSION > 4
|
||||
// Note that we have to use a std::string to allocate memory to ensure a unique address
|
||||
// We want unique addresses since we use pointer equality to compare function records
|
||||
std::string function_record_capsule_name = internals_function_record_capsule_name;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
internals() = default;
|
||||
internals(const internals &other) = delete;
|
||||
internals &operator=(const internals &other) = delete;
|
||||
~internals() {
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
#if PYBIND11_INTERNALS_VERSION > 4
|
||||
PYBIND11_TLS_FREE(loader_life_support_tls_key);
|
||||
# endif // PYBIND11_INTERNALS_VERSION > 4
|
||||
#endif // PYBIND11_INTERNALS_VERSION > 4
|
||||
|
||||
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
|
||||
// That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
|
||||
@ -224,7 +223,6 @@ struct internals {
|
||||
// that the `tstate` be allocated with the CPython allocator.
|
||||
PYBIND11_TLS_FREE(tstate);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Additional type information which does not fit into the PyTypeObject.
|
||||
@ -309,22 +307,18 @@ struct type_info {
|
||||
#endif
|
||||
|
||||
#ifndef PYBIND11_INTERNALS_KIND
|
||||
# if defined(WITH_THREAD)
|
||||
# define PYBIND11_INTERNALS_KIND ""
|
||||
# else
|
||||
# define PYBIND11_INTERNALS_KIND "_without_thread"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define PYBIND11_INTERNALS_ID \
|
||||
"__pybind11_internals_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
|
||||
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB PYBIND11_BUILD_ABI \
|
||||
PYBIND11_BUILD_TYPE "__"
|
||||
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB \
|
||||
PYBIND11_BUILD_ABI PYBIND11_BUILD_TYPE "__"
|
||||
|
||||
#define PYBIND11_MODULE_LOCAL_ID \
|
||||
"__pybind11_module_local_v" PYBIND11_TOSTRING(PYBIND11_INTERNALS_VERSION) \
|
||||
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB PYBIND11_BUILD_ABI \
|
||||
PYBIND11_BUILD_TYPE "__"
|
||||
PYBIND11_INTERNALS_KIND PYBIND11_COMPILER_TYPE PYBIND11_STDLIB \
|
||||
PYBIND11_BUILD_ABI PYBIND11_BUILD_TYPE "__"
|
||||
|
||||
/// Each module locally stores a pointer to the `internals` data. The data
|
||||
/// itself is shared among modules with the same `PYBIND11_INTERNALS_ID`.
|
||||
@ -462,7 +456,8 @@ inline object get_python_state_dict() {
|
||||
}
|
||||
|
||||
inline object get_internals_obj_from_state_dict(handle state_dict) {
|
||||
return reinterpret_borrow<object>(dict_getitemstring(state_dict.ptr(), PYBIND11_INTERNALS_ID));
|
||||
return reinterpret_steal<object>(
|
||||
dict_getitemstringref(state_dict.ptr(), PYBIND11_INTERNALS_ID));
|
||||
}
|
||||
|
||||
inline internals **get_internals_pp_from_capsule(handle obj) {
|
||||
@ -474,6 +469,20 @@ inline internals **get_internals_pp_from_capsule(handle obj) {
|
||||
return static_cast<internals **>(raw_ptr);
|
||||
}
|
||||
|
||||
inline uint64_t round_up_to_next_pow2(uint64_t x) {
|
||||
// Round-up to the next power of two.
|
||||
// See https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
x--;
|
||||
x |= (x >> 1);
|
||||
x |= (x >> 2);
|
||||
x |= (x >> 4);
|
||||
x |= (x >> 8);
|
||||
x |= (x >> 16);
|
||||
x |= (x >> 32);
|
||||
x++;
|
||||
return x;
|
||||
}
|
||||
|
||||
/// Return a reference to the current `internals` data
|
||||
PYBIND11_NOINLINE internals &get_internals() {
|
||||
auto **&internals_pp = get_internals_pp();
|
||||
@ -481,10 +490,9 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
return **internals_pp;
|
||||
}
|
||||
|
||||
#if defined(WITH_THREAD)
|
||||
# if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
gil_scoped_acquire gil;
|
||||
# else
|
||||
#else
|
||||
// Ensure that the GIL is held since we will need to make Python calls.
|
||||
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
|
||||
struct gil_scoped_acquire_local {
|
||||
@ -494,7 +502,6 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
~gil_scoped_acquire_local() { PyGILState_Release(state); }
|
||||
const PyGILState_STATE state;
|
||||
} gil;
|
||||
# endif
|
||||
#endif
|
||||
error_scope err_scope;
|
||||
|
||||
@ -519,7 +526,6 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
}
|
||||
auto *&internals_ptr = *internals_pp;
|
||||
internals_ptr = new internals();
|
||||
#if defined(WITH_THREAD)
|
||||
|
||||
PyThreadState *tstate = PyThreadState_Get();
|
||||
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||
@ -528,20 +534,29 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
}
|
||||
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate);
|
||||
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
#if PYBIND11_INTERNALS_VERSION > 4
|
||||
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
|
||||
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->loader_life_support_tls_key)) {
|
||||
pybind11_fail("get_internals: could not successfully initialize the "
|
||||
"loader_life_support TSS key!");
|
||||
}
|
||||
# endif
|
||||
internals_ptr->istate = tstate->interp;
|
||||
#endif
|
||||
internals_ptr->istate = tstate->interp;
|
||||
state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp);
|
||||
internals_ptr->registered_exception_translators.push_front(&translate_exception);
|
||||
internals_ptr->static_property_type = make_static_property_type();
|
||||
internals_ptr->default_metaclass = make_default_metaclass();
|
||||
internals_ptr->instance_base = make_object_base_type(internals_ptr->default_metaclass);
|
||||
#ifdef Py_GIL_DISABLED
|
||||
// Scale proportional to the number of cores. 2x is a heuristic to reduce contention.
|
||||
auto num_shards
|
||||
= static_cast<size_t>(round_up_to_next_pow2(2 * std::thread::hardware_concurrency()));
|
||||
if (num_shards == 0) {
|
||||
num_shards = 1;
|
||||
}
|
||||
internals_ptr->instance_shards.reset(new instance_map_shard[num_shards]);
|
||||
internals_ptr->instance_shards_mask = num_shards - 1;
|
||||
#endif // Py_GIL_DISABLED
|
||||
}
|
||||
return **internals_pp;
|
||||
}
|
||||
@ -555,7 +570,7 @@ PYBIND11_NOINLINE internals &get_internals() {
|
||||
struct local_internals {
|
||||
type_map<type_info *> registered_types_cpp;
|
||||
std::forward_list<ExceptionTranslator> registered_exception_translators;
|
||||
#if defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
|
||||
#if PYBIND11_INTERNALS_VERSION == 4
|
||||
|
||||
// For ABI compatibility, we can't store the loader_life_support TLS key in
|
||||
// the `internals` struct directly. Instead, we store it in `shared_data` and
|
||||
@ -588,7 +603,7 @@ struct local_internals {
|
||||
loader_life_support_tls_key
|
||||
= static_cast<shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key;
|
||||
}
|
||||
#endif // defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
|
||||
#endif // PYBIND11_INTERNALS_VERSION == 4
|
||||
};
|
||||
|
||||
/// Works like `get_internals`, but for things which are locally registered.
|
||||
@ -602,13 +617,80 @@ inline local_internals &get_local_internals() {
|
||||
return *locals;
|
||||
}
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
# define PYBIND11_LOCK_INTERNALS(internals) std::unique_lock<std::mutex> lock((internals).mutex)
|
||||
#else
|
||||
# define PYBIND11_LOCK_INTERNALS(internals)
|
||||
#endif
|
||||
|
||||
template <typename F>
|
||||
inline auto with_internals(const F &cb) -> decltype(cb(get_internals())) {
|
||||
auto &internals = get_internals();
|
||||
PYBIND11_LOCK_INTERNALS(internals);
|
||||
return cb(internals);
|
||||
}
|
||||
|
||||
inline std::uint64_t mix64(std::uint64_t z) {
|
||||
// David Stafford's variant 13 of the MurmurHash3 finalizer popularized
|
||||
// by the SplitMix PRNG.
|
||||
// https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html
|
||||
z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
|
||||
z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
|
||||
return z ^ (z >> 31);
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
inline auto with_instance_map(const void *ptr,
|
||||
const F &cb) -> decltype(cb(std::declval<instance_map &>())) {
|
||||
auto &internals = get_internals();
|
||||
|
||||
#ifdef Py_GIL_DISABLED
|
||||
// Hash address to compute shard, but ignore low bits. We'd like allocations
|
||||
// from the same thread/core to map to the same shard and allocations from
|
||||
// other threads/cores to map to other shards. Using the high bits is a good
|
||||
// heuristic because memory allocators often have a per-thread
|
||||
// arena/superblock/segment from which smaller allocations are served.
|
||||
auto addr = reinterpret_cast<std::uintptr_t>(ptr);
|
||||
auto hash = mix64(static_cast<std::uint64_t>(addr >> 20));
|
||||
auto idx = static_cast<size_t>(hash & internals.instance_shards_mask);
|
||||
|
||||
auto &shard = internals.instance_shards[idx];
|
||||
std::unique_lock<std::mutex> lock(shard.mutex);
|
||||
return cb(shard.registered_instances);
|
||||
#else
|
||||
(void) ptr;
|
||||
return cb(internals.registered_instances);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns the number of registered instances for testing purposes. The result may not be
|
||||
// consistent if other threads are registering or unregistering instances concurrently.
|
||||
inline size_t num_registered_instances() {
|
||||
auto &internals = get_internals();
|
||||
#ifdef Py_GIL_DISABLED
|
||||
size_t count = 0;
|
||||
for (size_t i = 0; i <= internals.instance_shards_mask; ++i) {
|
||||
auto &shard = internals.instance_shards[i];
|
||||
std::unique_lock<std::mutex> lock(shard.mutex);
|
||||
count += shard.registered_instances.size();
|
||||
}
|
||||
return count;
|
||||
#else
|
||||
return internals.registered_instances.size();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Constructs a std::string with the given arguments, stores it in `internals`, and returns its
|
||||
/// `c_str()`. Such strings objects have a long storage duration -- the internal strings are only
|
||||
/// cleared when the program exits or after interpreter shutdown (when embedding), and so are
|
||||
/// suitable for c-style strings needed by Python internals (such as PyTypeObject's tp_name).
|
||||
template <typename... Args>
|
||||
const char *c_str(Args &&...args) {
|
||||
auto &strings = get_internals().static_strings;
|
||||
// GCC 4.8 doesn't like parameter unpack within lambda capture, so use
|
||||
// PYBIND11_LOCK_INTERNALS.
|
||||
auto &internals = get_internals();
|
||||
PYBIND11_LOCK_INTERNALS(internals);
|
||||
auto &strings = internals.static_strings;
|
||||
strings.emplace_front(std::forward<Args>(args)...);
|
||||
return strings.front().c_str();
|
||||
}
|
||||
@ -638,15 +720,18 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
/// pybind11 version) running in the current interpreter. Names starting with underscores
|
||||
/// are reserved for internal usage. Returns `nullptr` if no matching entry was found.
|
||||
PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
|
||||
auto &internals = detail::get_internals();
|
||||
return detail::with_internals([&](detail::internals &internals) {
|
||||
auto it = internals.shared_data.find(name);
|
||||
return it != internals.shared_data.end() ? it->second : nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
/// Set the shared data that can be later recovered by `get_shared_data()`.
|
||||
PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
|
||||
detail::get_internals().shared_data[name] = data;
|
||||
return detail::with_internals([&](detail::internals &internals) {
|
||||
internals.shared_data[name] = data;
|
||||
return data;
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if
|
||||
@ -654,14 +739,15 @@ PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
|
||||
/// added to the shared data under the given name and a reference to it is returned.
|
||||
template <typename T>
|
||||
T &get_or_create_shared_data(const std::string &name) {
|
||||
auto &internals = detail::get_internals();
|
||||
return *detail::with_internals([&](detail::internals &internals) {
|
||||
auto it = internals.shared_data.find(name);
|
||||
T *ptr = (T *) (it != internals.shared_data.end() ? it->second : nullptr);
|
||||
if (!ptr) {
|
||||
ptr = new T();
|
||||
internals.shared_data[name] = ptr;
|
||||
}
|
||||
return *ptr;
|
||||
return ptr;
|
||||
});
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
@ -36,14 +36,13 @@ private:
|
||||
loader_life_support *parent = nullptr;
|
||||
std::unordered_set<PyObject *> keep_alive;
|
||||
|
||||
#if defined(WITH_THREAD)
|
||||
// Store stack pointer in thread-local storage.
|
||||
static PYBIND11_TLS_KEY_REF get_stack_tls_key() {
|
||||
# if PYBIND11_INTERNALS_VERSION == 4
|
||||
#if PYBIND11_INTERNALS_VERSION == 4
|
||||
return get_local_internals().loader_life_support_tls_key;
|
||||
# else
|
||||
#else
|
||||
return get_internals().loader_life_support_tls_key;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
static loader_life_support *get_stack_top() {
|
||||
return static_cast<loader_life_support *>(PYBIND11_TLS_GET_VALUE(get_stack_tls_key()));
|
||||
@ -51,15 +50,6 @@ private:
|
||||
static void set_stack_top(loader_life_support *value) {
|
||||
PYBIND11_TLS_REPLACE_VALUE(get_stack_tls_key(), value);
|
||||
}
|
||||
#else
|
||||
// Use single global variable for stack.
|
||||
static loader_life_support **get_stack_pp() {
|
||||
static loader_life_support *global_stack = nullptr;
|
||||
return global_stack;
|
||||
}
|
||||
static loader_life_support *get_stack_top() { return *get_stack_pp(); }
|
||||
static void set_stack_top(loader_life_support *value) { *get_stack_pp() = value; }
|
||||
#endif
|
||||
|
||||
public:
|
||||
/// A new patient frame is created when a function is entered
|
||||
@ -217,12 +207,15 @@ inline detail::type_info *get_local_type_info(const std::type_index &tp) {
|
||||
}
|
||||
|
||||
inline detail::type_info *get_global_type_info(const std::type_index &tp) {
|
||||
auto &types = get_internals().registered_types_cpp;
|
||||
return with_internals([&](internals &internals) {
|
||||
detail::type_info *type_info = nullptr;
|
||||
auto &types = internals.registered_types_cpp;
|
||||
auto it = types.find(tp);
|
||||
if (it != types.end()) {
|
||||
return it->second;
|
||||
type_info = it->second;
|
||||
}
|
||||
return nullptr;
|
||||
return type_info;
|
||||
});
|
||||
}
|
||||
|
||||
/// Return the type info for a given C++ type; on lookup failure can either throw or return
|
||||
@ -253,7 +246,8 @@ PYBIND11_NOINLINE handle get_type_handle(const std::type_info &tp, bool throw_if
|
||||
// Searches the inheritance graph for a registered Python instance, using all_type_info().
|
||||
PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
|
||||
const detail::type_info *tinfo) {
|
||||
auto it_instances = get_internals().registered_instances.equal_range(src);
|
||||
return with_instance_map(src, [&](instance_map &instances) {
|
||||
auto it_instances = instances.equal_range(src);
|
||||
for (auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) {
|
||||
for (auto *instance_type : detail::all_type_info(Py_TYPE(it_i->second))) {
|
||||
if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype)) {
|
||||
@ -262,6 +256,7 @@ PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
|
||||
}
|
||||
}
|
||||
return handle();
|
||||
});
|
||||
}
|
||||
|
||||
struct value_and_holder {
|
||||
@ -506,7 +501,7 @@ PYBIND11_NOINLINE bool isinstance_generic(handle obj, const std::type_info &tp)
|
||||
}
|
||||
|
||||
PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_info *type) {
|
||||
auto &instances = get_internals().registered_instances;
|
||||
return with_instance_map(ptr, [&](instance_map &instances) {
|
||||
auto range = instances.equal_range(ptr);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
for (const auto &vh : values_and_holders(it->second)) {
|
||||
@ -516,6 +511,7 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
|
||||
}
|
||||
}
|
||||
return handle();
|
||||
});
|
||||
}
|
||||
|
||||
inline PyThreadState *get_thread_state_unchecked() {
|
||||
@ -1111,11 +1107,11 @@ public:
|
||||
|| policy == return_value_policy::automatic_reference) {
|
||||
policy = return_value_policy::copy;
|
||||
}
|
||||
return cast(&src, policy, parent);
|
||||
return cast(std::addressof(src), policy, parent);
|
||||
}
|
||||
|
||||
static handle cast(itype &&src, return_value_policy, handle parent) {
|
||||
return cast(&src, return_value_policy::move, parent);
|
||||
return cast(std::addressof(src), return_value_policy::move, parent);
|
||||
}
|
||||
|
||||
// Returns a (pointer, type_info) pair taking care of necessary type lookup for a
|
||||
@ -1184,14 +1180,14 @@ protected:
|
||||
does not have a private operator new implementation. A comma operator is used in the
|
||||
decltype argument to apply SFINAE to the public copy/move constructors.*/
|
||||
template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
|
||||
static auto make_copy_constructor(const T *)
|
||||
-> decltype(new T(std::declval<const T>()), Constructor{}) {
|
||||
static auto make_copy_constructor(const T *) -> decltype(new T(std::declval<const T>()),
|
||||
Constructor{}) {
|
||||
return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
|
||||
}
|
||||
|
||||
template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
|
||||
static auto make_move_constructor(const T *)
|
||||
-> decltype(new T(std::declval<T &&>()), Constructor{}) {
|
||||
static auto make_move_constructor(const T *) -> decltype(new T(std::declval<T &&>()),
|
||||
Constructor{}) {
|
||||
return [](const void *arg) -> void * {
|
||||
return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
|
||||
};
|
||||
|
@ -103,9 +103,6 @@ inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
|
||||
bool add_program_dir_to_path) {
|
||||
detail::precheck_interpreter();
|
||||
Py_InitializeEx(init_signal_handlers ? 1 : 0);
|
||||
# if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
|
||||
PyEval_InitThreads();
|
||||
# endif
|
||||
|
||||
// Before it was special-cased in python 3.8, passing an empty or null argv
|
||||
// caused a segfault, so we have to reimplement the special case ourselves.
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
#if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
# include "detail/internals.h"
|
||||
#endif
|
||||
|
||||
@ -26,9 +26,7 @@ PyThreadState *get_thread_state_unchecked();
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
#if defined(WITH_THREAD)
|
||||
|
||||
# if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
#if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
|
||||
/* The functions below essentially reproduce the PyGILState_* API using a RAII
|
||||
* pattern, but there are a few important differences:
|
||||
@ -188,7 +186,7 @@ private:
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
# else // PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||
#else // PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||
|
||||
class gil_scoped_acquire {
|
||||
PyGILState_STATE state;
|
||||
@ -216,32 +214,6 @@ public:
|
||||
void disarm() {}
|
||||
};
|
||||
|
||||
# endif // PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||
|
||||
#else // WITH_THREAD
|
||||
|
||||
class gil_scoped_acquire {
|
||||
public:
|
||||
gil_scoped_acquire() {
|
||||
// Trick to suppress `unused variable` error messages (at call sites).
|
||||
(void) (this != (this + 1));
|
||||
}
|
||||
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
|
||||
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
|
||||
void disarm() {}
|
||||
};
|
||||
|
||||
class gil_scoped_release {
|
||||
public:
|
||||
gil_scoped_release() {
|
||||
// Trick to suppress `unused variable` error messages (at call sites).
|
||||
(void) (this != (this + 1));
|
||||
}
|
||||
gil_scoped_release(const gil_scoped_release &) = delete;
|
||||
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
|
||||
void disarm() {}
|
||||
};
|
||||
|
||||
#endif // WITH_THREAD
|
||||
#endif // PYBIND11_SIMPLE_GIL_MANAGEMENT
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
@ -1553,7 +1553,9 @@ PYBIND11_NOINLINE void register_structured_dtype(any_container<field_descriptor>
|
||||
|
||||
auto tindex = std::type_index(tinfo);
|
||||
numpy_internals.registered_dtypes[tindex] = {dtype_ptr, std::move(format_str)};
|
||||
get_internals().direct_conversions[tindex].push_back(direct_converter);
|
||||
with_internals([tindex, &direct_converter](internals &internals) {
|
||||
internals.direct_conversions[tindex].push_back(direct_converter);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T, typename SFINAE>
|
||||
|
@ -1054,13 +1054,20 @@ protected:
|
||||
- delegate translation to the next translator by throwing a new type of exception.
|
||||
*/
|
||||
|
||||
bool handled = with_internals([&](internals &internals) {
|
||||
auto &local_exception_translators
|
||||
= get_local_internals().registered_exception_translators;
|
||||
if (detail::apply_exception_translators(local_exception_translators)) {
|
||||
return nullptr;
|
||||
return true;
|
||||
}
|
||||
auto &exception_translators = get_internals().registered_exception_translators;
|
||||
auto &exception_translators = internals.registered_exception_translators;
|
||||
if (detail::apply_exception_translators(exception_translators)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (handled) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -1199,6 +1206,16 @@ struct handle_type_name<cpp_function> {
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
// Use to activate Py_MOD_GIL_NOT_USED.
|
||||
class mod_gil_not_used {
|
||||
public:
|
||||
explicit mod_gil_not_used(bool flag = true) : flag_(flag) {}
|
||||
bool flag() const { return flag_; }
|
||||
|
||||
private:
|
||||
bool flag_;
|
||||
};
|
||||
|
||||
/// Wrapper for Python extension modules
|
||||
class module_ : public object {
|
||||
public:
|
||||
@ -1299,7 +1316,11 @@ public:
|
||||
|
||||
``def`` should point to a statically allocated module_def.
|
||||
\endrst */
|
||||
static module_ create_extension_module(const char *name, const char *doc, module_def *def) {
|
||||
static module_ create_extension_module(const char *name,
|
||||
const char *doc,
|
||||
module_def *def,
|
||||
mod_gil_not_used gil_not_used
|
||||
= mod_gil_not_used(false)) {
|
||||
// module_def is PyModuleDef
|
||||
// Placement new (not an allocation).
|
||||
def = new (def)
|
||||
@ -1319,6 +1340,11 @@ public:
|
||||
}
|
||||
pybind11_fail("Internal error in module_::create_extension_module()");
|
||||
}
|
||||
if (gil_not_used.flag()) {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
||||
#endif
|
||||
}
|
||||
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when
|
||||
// returned from PyInit_...
|
||||
// For Python 2, reinterpret_borrow was correct.
|
||||
@ -1344,8 +1370,14 @@ using module = module_;
|
||||
/// Return a dictionary representing the global variables in the current execution frame,
|
||||
/// or ``__main__.__dict__`` if there is no frame (usually when the interpreter is embedded).
|
||||
inline dict globals() {
|
||||
#if PY_VERSION_HEX >= 0x030d0000
|
||||
PyObject *p = PyEval_GetFrameGlobals();
|
||||
return p ? reinterpret_steal<dict>(p)
|
||||
: reinterpret_borrow<dict>(module_::import("__main__").attr("__dict__").ptr());
|
||||
#else
|
||||
PyObject *p = PyEval_GetGlobals();
|
||||
return reinterpret_borrow<dict>(p ? p : module_::import("__main__").attr("__dict__").ptr());
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename... Args, typename = detail::enable_if_t<args_are_all_keyword_or_ds<Args...>()>>
|
||||
@ -1391,7 +1423,7 @@ protected:
|
||||
tinfo->default_holder = rec.default_holder;
|
||||
tinfo->module_local = rec.module_local;
|
||||
|
||||
auto &internals = get_internals();
|
||||
with_internals([&](internals &internals) {
|
||||
auto tindex = std::type_index(*rec.type);
|
||||
tinfo->direct_conversions = &internals.direct_conversions[tindex];
|
||||
if (rec.module_local) {
|
||||
@ -1400,6 +1432,7 @@ protected:
|
||||
internals.registered_types_cpp[tindex] = tinfo;
|
||||
}
|
||||
internals.registered_types_py[(PyTypeObject *) m_ptr] = {tinfo};
|
||||
});
|
||||
|
||||
if (rec.bases.size() > 1 || rec.multiple_inheritance) {
|
||||
mark_parents_nonsimple(tinfo->type);
|
||||
@ -1612,10 +1645,12 @@ public:
|
||||
generic_type::initialize(record);
|
||||
|
||||
if (has_alias) {
|
||||
with_internals([&](internals &internals) {
|
||||
auto &instances = record.module_local ? get_local_internals().registered_types_cpp
|
||||
: get_internals().registered_types_cpp;
|
||||
: internals.registered_types_cpp;
|
||||
instances[std::type_index(typeid(type_alias))]
|
||||
= instances[std::type_index(typeid(type))];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -2330,21 +2365,24 @@ keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret) {
|
||||
|
||||
inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
|
||||
all_type_info_get_cache(PyTypeObject *type) {
|
||||
auto res = get_internals()
|
||||
auto res = with_internals([type](internals &internals) {
|
||||
return internals
|
||||
.registered_types_py
|
||||
#ifdef __cpp_lib_unordered_map_try_emplace
|
||||
.try_emplace(type);
|
||||
#else
|
||||
.emplace(type, std::vector<detail::type_info *>());
|
||||
#endif
|
||||
});
|
||||
if (res.second) {
|
||||
// New cache entry created; set up a weak reference to automatically remove it if the type
|
||||
// gets destroyed:
|
||||
weakref((PyObject *) type, cpp_function([type](handle wr) {
|
||||
get_internals().registered_types_py.erase(type);
|
||||
with_internals([type](internals &internals) {
|
||||
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;
|
||||
auto &cache = 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);
|
||||
@ -2352,6 +2390,7 @@ all_type_info_get_cache(PyTypeObject *type) {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
wr.dec_ref();
|
||||
}))
|
||||
@ -2556,7 +2595,11 @@ void implicitly_convertible() {
|
||||
~set_flag() { flag = false; }
|
||||
};
|
||||
auto implicit_caster = [](PyObject *obj, PyTypeObject *type) -> PyObject * {
|
||||
#ifdef Py_GIL_DISABLED
|
||||
thread_local bool currently_used = false;
|
||||
#else
|
||||
static bool currently_used = false;
|
||||
#endif
|
||||
if (currently_used) { // implicit conversions are non-reentrant
|
||||
return nullptr;
|
||||
}
|
||||
@ -2581,8 +2624,10 @@ void implicitly_convertible() {
|
||||
}
|
||||
|
||||
inline void register_exception_translator(ExceptionTranslator &&translator) {
|
||||
detail::get_internals().registered_exception_translators.push_front(
|
||||
detail::with_internals([&](detail::internals &internals) {
|
||||
internals.registered_exception_translators.push_front(
|
||||
std::forward<ExceptionTranslator>(translator));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2592,8 +2637,11 @@ inline void register_exception_translator(ExceptionTranslator &&translator) {
|
||||
* the exception.
|
||||
*/
|
||||
inline void register_local_exception_translator(ExceptionTranslator &&translator) {
|
||||
detail::with_internals([&](detail::internals &internals) {
|
||||
(void) internals;
|
||||
detail::get_local_internals().registered_exception_translators.push_front(
|
||||
std::forward<ExceptionTranslator>(translator));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2750,14 +2798,19 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
|
||||
|
||||
/* Cache functions that aren't overridden in Python to avoid
|
||||
many costly Python dictionary lookups below */
|
||||
auto &cache = get_internals().inactive_override_cache;
|
||||
if (cache.find(key) != cache.end()) {
|
||||
bool not_overridden = with_internals([&key](internals &internals) {
|
||||
auto &cache = internals.inactive_override_cache;
|
||||
return cache.find(key) != cache.end();
|
||||
});
|
||||
if (not_overridden) {
|
||||
return function();
|
||||
}
|
||||
|
||||
function override = getattr(self, name, function());
|
||||
if (override.is_cpp_function()) {
|
||||
cache.insert(std::move(key));
|
||||
with_internals([&](internals &internals) {
|
||||
internals.inactive_override_cache.insert(std::move(key));
|
||||
});
|
||||
return function();
|
||||
}
|
||||
|
||||
@ -2770,7 +2823,12 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
|
||||
PyCodeObject *f_code = PyFrame_GetCode(frame);
|
||||
// f_code is guaranteed to not be NULL
|
||||
if ((std::string) str(f_code->co_name) == name && f_code->co_argcount > 0) {
|
||||
# if PY_VERSION_HEX >= 0x030d0000
|
||||
PyObject *locals = PyEval_GetFrameLocals();
|
||||
# else
|
||||
PyObject *locals = PyEval_GetLocals();
|
||||
Py_XINCREF(locals);
|
||||
# endif
|
||||
if (locals != nullptr) {
|
||||
# if PY_VERSION_HEX >= 0x030b0000
|
||||
PyObject *co_varnames = PyCode_GetVarnames(f_code);
|
||||
@ -2780,6 +2838,7 @@ get_type_override(const void *this_ptr, const type_info *this_type, const char *
|
||||
PyObject *self_arg = PyTuple_GET_ITEM(co_varnames, 0);
|
||||
Py_DECREF(co_varnames);
|
||||
PyObject *self_caller = dict_getitem(locals, self_arg);
|
||||
Py_DECREF(locals);
|
||||
if (self_caller == self.ptr()) {
|
||||
Py_DECREF(f_code);
|
||||
Py_DECREF(frame);
|
||||
@ -2856,10 +2915,14 @@ function get_override(const T *this_ptr, const char *name) {
|
||||
= pybind11::get_override(static_cast<const cname *>(this), name); \
|
||||
if (override) { \
|
||||
auto o = override(__VA_ARGS__); \
|
||||
if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value) { \
|
||||
PYBIND11_WARNING_PUSH \
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4127) \
|
||||
if (pybind11::detail::cast_is_temporary_value_reference<ret_type>::value \
|
||||
&& !pybind11::detail::is_same_ignoring_cvref<ret_type, PyObject *>::value) { \
|
||||
static pybind11::detail::override_caster_t<ret_type> caster; \
|
||||
return pybind11::detail::cast_ref<ret_type>(std::move(o), caster); \
|
||||
} \
|
||||
PYBIND11_WARNING_POP \
|
||||
return pybind11::detail::cast_safe<ret_type>(std::move(o)); \
|
||||
} \
|
||||
} while (false)
|
||||
|
@ -183,7 +183,15 @@ public:
|
||||
str_attr_accessor doc() const;
|
||||
|
||||
/// Return the object's current reference count
|
||||
int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); }
|
||||
ssize_t ref_count() const {
|
||||
#ifdef PYPY_VERSION
|
||||
// PyPy uses the top few bits for REFCNT_FROM_PYPY & REFCNT_FROM_PYPY_LIGHT
|
||||
// Following pybind11 2.12.1 and older behavior and removing this part
|
||||
return static_cast<ssize_t>(static_cast<int>(Py_REFCNT(derived().ptr())));
|
||||
#else
|
||||
return Py_REFCNT(derived().ptr());
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO PYBIND11_DEPRECATED(
|
||||
// "Call py::type::handle_of(h) or py::type::of(h) instead of h.get_type()")
|
||||
@ -972,6 +980,23 @@ inline PyObject *dict_getitem(PyObject *v, PyObject *key) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
inline PyObject *dict_getitemstringref(PyObject *v, const char *key) {
|
||||
#if PY_VERSION_HEX >= 0x030D0000
|
||||
PyObject *rv;
|
||||
if (PyDict_GetItemStringRef(v, key, &rv) < 0) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return rv;
|
||||
#else
|
||||
PyObject *rv = dict_getitemstring(v, key);
|
||||
if (rv == nullptr && PyErr_Occurred()) {
|
||||
throw error_already_set();
|
||||
}
|
||||
Py_XINCREF(rv);
|
||||
return rv;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper aliases/functions to support implicit casting of values given to python
|
||||
// accessors/methods. When given a pyobject, this simply returns the pyobject as-is; for other C++
|
||||
// type, the value goes through pybind11::cast(obj) to convert it to an `object`.
|
||||
@ -2175,6 +2200,11 @@ public:
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
void clear() /* py-non-const */ {
|
||||
if (PyList_SetSlice(m_ptr, 0, PyList_Size(m_ptr), nullptr) == -1) {
|
||||
throw error_already_set();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class args : public tuple {
|
||||
|
@ -14,8 +14,7 @@
|
||||
|
||||
#ifdef __has_include
|
||||
# if defined(PYBIND11_CPP17)
|
||||
# if __has_include(<filesystem>) && \
|
||||
PY_VERSION_HEX >= 0x03060000
|
||||
# if __has_include(<filesystem>)
|
||||
# include <filesystem>
|
||||
# define PYBIND11_HAS_FILESYSTEM 1
|
||||
# elif __has_include(<experimental/filesystem>)
|
||||
|
@ -158,8 +158,7 @@ void vector_modifiers(
|
||||
return v.release();
|
||||
}));
|
||||
|
||||
cl.def(
|
||||
"clear", [](Vector &v) { v.clear(); }, "Clear the contents");
|
||||
cl.def("clear", [](Vector &v) { v.clear(); }, "Clear the contents");
|
||||
|
||||
cl.def(
|
||||
"extend",
|
||||
|
@ -63,6 +63,62 @@ class Callable<Return(Args...)> : public function {
|
||||
using function::function;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Type : public type {
|
||||
using type::type;
|
||||
};
|
||||
|
||||
template <typename... Types>
|
||||
class Union : public object {
|
||||
PYBIND11_OBJECT_DEFAULT(Union, object, PyObject_Type)
|
||||
using object::object;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class Optional : public object {
|
||||
PYBIND11_OBJECT_DEFAULT(Optional, object, PyObject_Type)
|
||||
using object::object;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypeGuard : public bool_ {
|
||||
using bool_::bool_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class TypeIs : public bool_ {
|
||||
using bool_::bool_;
|
||||
};
|
||||
|
||||
class NoReturn : public none {
|
||||
using none::none;
|
||||
};
|
||||
|
||||
class Never : public none {
|
||||
using none::none;
|
||||
};
|
||||
|
||||
#if defined(__cpp_nontype_template_parameter_class)
|
||||
template <size_t N>
|
||||
struct StringLiteral {
|
||||
constexpr StringLiteral(const char (&str)[N]) { std::copy_n(str, N, name); }
|
||||
char name[N];
|
||||
};
|
||||
|
||||
template <StringLiteral... StrLits>
|
||||
class Literal : public object {
|
||||
PYBIND11_OBJECT_DEFAULT(Literal, object, PyObject_Type)
|
||||
};
|
||||
|
||||
// Example syntax for creating a TypeVar.
|
||||
// typedef typing::TypeVar<"T"> TypeVarT;
|
||||
template <StringLiteral>
|
||||
class TypeVar : public object {
|
||||
PYBIND11_OBJECT_DEFAULT(TypeVar, object, PyObject_Type)
|
||||
using object::object;
|
||||
};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(typing)
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
@ -121,5 +177,55 @@ struct handle_type_name<typing::Callable<Return(Args...)>> {
|
||||
+ const_name("], ") + make_caster<retval_type>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct handle_type_name<typing::Type<T>> {
|
||||
static constexpr auto name = const_name("type[") + make_caster<T>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <typename... Types>
|
||||
struct handle_type_name<typing::Union<Types...>> {
|
||||
static constexpr auto name = const_name("Union[")
|
||||
+ ::pybind11::detail::concat(make_caster<Types>::name...)
|
||||
+ const_name("]");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct handle_type_name<typing::Optional<T>> {
|
||||
static constexpr auto name = const_name("Optional[") + make_caster<T>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct handle_type_name<typing::TypeGuard<T>> {
|
||||
static constexpr auto name = const_name("TypeGuard[") + make_caster<T>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct handle_type_name<typing::TypeIs<T>> {
|
||||
static constexpr auto name = const_name("TypeIs[") + make_caster<T>::name + const_name("]");
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handle_type_name<typing::NoReturn> {
|
||||
static constexpr auto name = const_name("NoReturn");
|
||||
};
|
||||
|
||||
template <>
|
||||
struct handle_type_name<typing::Never> {
|
||||
static constexpr auto name = const_name("Never");
|
||||
};
|
||||
|
||||
#if defined(__cpp_nontype_template_parameter_class)
|
||||
template <typing::StringLiteral... Literals>
|
||||
struct handle_type_name<typing::Literal<Literals...>> {
|
||||
static constexpr auto name = const_name("Literal[")
|
||||
+ pybind11::detail::concat(const_name(Literals.name)...)
|
||||
+ const_name("]");
|
||||
};
|
||||
template <typing::StringLiteral StrLit>
|
||||
struct handle_type_name<typing::TypeVar<StrLit>> {
|
||||
static constexpr auto name = const_name(StrLit.name);
|
||||
};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
62
noxfile.py
62
noxfile.py
@ -1,24 +1,12 @@
|
||||
import os
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
|
||||
import nox
|
||||
|
||||
nox.needs_version = ">=2022.1.7"
|
||||
nox.needs_version = ">=2024.3.2"
|
||||
nox.options.sessions = ["lint", "tests", "tests_packaging"]
|
||||
|
||||
PYTHON_VERSIONS = [
|
||||
"3.6",
|
||||
"3.7",
|
||||
"3.8",
|
||||
"3.9",
|
||||
"3.10",
|
||||
"3.11",
|
||||
"pypy3.7",
|
||||
"pypy3.8",
|
||||
"pypy3.9",
|
||||
]
|
||||
|
||||
if os.environ.get("CI", None):
|
||||
nox.options.error_on_missing_interpreters = True
|
||||
nox.options.default_venv_backend = "uv|virtualenv"
|
||||
|
||||
|
||||
@nox.session(reuse_venv=True)
|
||||
@ -30,7 +18,7 @@ def lint(session: nox.Session) -> None:
|
||||
session.run("pre-commit", "run", "-a", *session.posargs)
|
||||
|
||||
|
||||
@nox.session(python=PYTHON_VERSIONS)
|
||||
@nox.session
|
||||
def tests(session: nox.Session) -> None:
|
||||
"""
|
||||
Run the tests (requires a compiler).
|
||||
@ -57,30 +45,42 @@ def tests_packaging(session: nox.Session) -> None:
|
||||
Run the packaging tests.
|
||||
"""
|
||||
|
||||
session.install("-r", "tests/requirements.txt")
|
||||
session.install("-r", "tests/requirements.txt", "pip")
|
||||
session.run("pytest", "tests/extra_python_package", *session.posargs)
|
||||
|
||||
|
||||
@nox.session(reuse_venv=True)
|
||||
def docs(session: nox.Session) -> None:
|
||||
"""
|
||||
Build the docs. Pass "serve" to serve.
|
||||
Build the docs. Pass --non-interactive to avoid serving.
|
||||
"""
|
||||
|
||||
session.install("-r", "docs/requirements.txt")
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
"-b", dest="builder", default="html", help="Build target (default: html)"
|
||||
)
|
||||
args, posargs = parser.parse_known_args(session.posargs)
|
||||
serve = args.builder == "html" and session.interactive
|
||||
|
||||
extra_installs = ["sphinx-autobuild"] if serve else []
|
||||
session.install("-r", "docs/requirements.txt", *extra_installs)
|
||||
session.chdir("docs")
|
||||
|
||||
if "pdf" in session.posargs:
|
||||
session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
|
||||
return
|
||||
shared_args = (
|
||||
"-n", # nitpicky mode
|
||||
"-T", # full tracebacks
|
||||
f"-b={args.builder}",
|
||||
".",
|
||||
f"_build/{args.builder}",
|
||||
*posargs,
|
||||
)
|
||||
|
||||
session.run("sphinx-build", "-M", "html", ".", "_build")
|
||||
|
||||
if "serve" in session.posargs:
|
||||
session.log("Launching docs at http://localhost:8000/ - use Ctrl-C to quit")
|
||||
session.run("python", "-m", "http.server", "8000", "-d", "_build/html")
|
||||
elif session.posargs:
|
||||
session.error("Unsupported argument to docs")
|
||||
if serve:
|
||||
session.run(
|
||||
"sphinx-autobuild", "--open-browser", "--ignore=.build", *shared_args
|
||||
)
|
||||
else:
|
||||
session.run("sphinx-build", "--keep-going", *shared_args)
|
||||
|
||||
|
||||
@nox.session(reuse_venv=True)
|
||||
|
@ -1,7 +1,9 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 6): # noqa: UP036
|
||||
msg = "pybind11 does not support Python < 3.6. 2.9 was the last release supporting Python 2.7 and 3.5."
|
||||
if sys.version_info < (3, 7): # noqa: UP036
|
||||
msg = "pybind11 does not support Python < 3.7. v2.12 was the last release supporting Python 3.6."
|
||||
raise ImportError(msg)
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
# pylint: disable=missing-function-docstring
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
@ -1,12 +1,12 @@
|
||||
from typing import Union
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
def _to_int(s: str) -> Union[int, str]:
|
||||
def _to_int(s: str) -> int | str:
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
return s
|
||||
|
||||
|
||||
__version__ = "2.12.0"
|
||||
__version__ = "2.13.0"
|
||||
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
|
@ -36,6 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# If you copy this file in, you don't
|
||||
# need the .pyi file; it's just an interface file for static type checkers.
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
@ -52,7 +53,6 @@ from pathlib import Path
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
@ -113,10 +113,10 @@ class Pybind11Extension(_Extension):
|
||||
# flags are prepended, so that they can be further overridden, e.g. by
|
||||
# ``extra_compile_args=["-g"]``.
|
||||
|
||||
def _add_cflags(self, flags: List[str]) -> None:
|
||||
def _add_cflags(self, flags: list[str]) -> None:
|
||||
self.extra_compile_args[:0] = flags
|
||||
|
||||
def _add_ldflags(self, flags: List[str]) -> None:
|
||||
def _add_ldflags(self, flags: list[str]) -> None:
|
||||
self.extra_link_args[:0] = flags
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
@ -250,7 +250,7 @@ cpp_flag_cache = None
|
||||
|
||||
|
||||
@lru_cache()
|
||||
def auto_cpp_level(compiler: Any) -> Union[str, int]:
|
||||
def auto_cpp_level(compiler: Any) -> str | int:
|
||||
"""
|
||||
Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows.
|
||||
"""
|
||||
@ -288,8 +288,8 @@ class build_ext(_build_ext): # noqa: N801
|
||||
|
||||
|
||||
def intree_extensions(
|
||||
paths: Iterable[str], package_dir: Optional[Dict[str, str]] = None
|
||||
) -> List[Pybind11Extension]:
|
||||
paths: Iterable[str], package_dir: dict[str, str] | None = None
|
||||
) -> list[Pybind11Extension]:
|
||||
"""
|
||||
Generate Pybind11Extensions from source files directly located in a Python
|
||||
source tree.
|
||||
@ -353,7 +353,7 @@ CCompilerMethod = Callable[
|
||||
distutils.ccompiler.CCompiler,
|
||||
List[str],
|
||||
Optional[str],
|
||||
Optional[Union[Tuple[str], Tuple[str, Optional[str]]]],
|
||||
Optional[List[Union[Tuple[str], Tuple[str, Optional[str]]]]],
|
||||
Optional[List[str]],
|
||||
bool,
|
||||
Optional[List[str]],
|
||||
@ -409,7 +409,7 @@ class ParallelCompile:
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
envvar: Optional[str] = None,
|
||||
envvar: str | None = None,
|
||||
default: int = 0,
|
||||
max: int = 0, # pylint: disable=redefined-builtin
|
||||
needs_recompile: Callable[[str, str], bool] = no_recompile,
|
||||
@ -418,7 +418,7 @@ class ParallelCompile:
|
||||
self.default = default
|
||||
self.max = max
|
||||
self.needs_recompile = needs_recompile
|
||||
self._old: List[CCompilerMethod] = []
|
||||
self._old: list[CCompilerMethod] = []
|
||||
|
||||
def function(self) -> CCompilerMethod:
|
||||
"""
|
||||
@ -427,14 +427,14 @@ class ParallelCompile:
|
||||
|
||||
def compile_function(
|
||||
compiler: distutils.ccompiler.CCompiler,
|
||||
sources: List[str],
|
||||
output_dir: Optional[str] = None,
|
||||
macros: Optional[Union[Tuple[str], Tuple[str, Optional[str]]]] = None,
|
||||
include_dirs: Optional[List[str]] = None,
|
||||
sources: list[str],
|
||||
output_dir: str | None = None,
|
||||
macros: list[tuple[str] | tuple[str, str | None]] | None = None,
|
||||
include_dirs: list[str] | None = None,
|
||||
debug: bool = False,
|
||||
extra_preargs: Optional[List[str]] = None,
|
||||
extra_postargs: Optional[List[str]] = None,
|
||||
depends: Optional[List[str]] = None,
|
||||
extra_preargs: list[str] | None = None,
|
||||
extra_postargs: list[str] | None = None,
|
||||
depends: list[str] | None = None,
|
||||
) -> Any:
|
||||
# These lines are directly from distutils.ccompiler.CCompiler
|
||||
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile( # type: ignore[attr-defined]
|
||||
|
@ -19,9 +19,8 @@ ignore = [
|
||||
|
||||
[tool.mypy]
|
||||
files = ["pybind11"]
|
||||
python_version = "3.7"
|
||||
python_version = "3.8"
|
||||
strict = true
|
||||
show_error_codes = true
|
||||
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
||||
warn_unreachable = true
|
||||
|
||||
@ -30,20 +29,8 @@ module = ["ghapi.*"]
|
||||
ignore_missing_imports = true
|
||||
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
minversion = "6.0"
|
||||
addopts = ["-ra", "--showlocals", "--strict-markers", "--strict-config"]
|
||||
xfail_strict = true
|
||||
filterwarnings = ["error"]
|
||||
log_cli_level = "info"
|
||||
testpaths = [
|
||||
"tests",
|
||||
]
|
||||
timeout=300
|
||||
|
||||
|
||||
[tool.pylint]
|
||||
master.py-version = "3.6"
|
||||
master.py-version = "3.7"
|
||||
reports.output-format = "colorized"
|
||||
messages_control.disable = [
|
||||
"design",
|
||||
@ -89,7 +76,12 @@ ignore = [
|
||||
]
|
||||
unfixable = ["T20"]
|
||||
isort.known-first-party = ["env", "pybind11_cross_module_tests", "pybind11_tests"]
|
||||
isort.required-imports = ["from __future__ import annotations"]
|
||||
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/**" = ["EM", "N", "E721"]
|
||||
"tests/test_call_policies.py" = ["PLC1901"]
|
||||
|
||||
[tool.repo-review]
|
||||
ignore = ["PP"]
|
||||
|
@ -14,13 +14,13 @@ classifiers =
|
||||
Topic :: Utilities
|
||||
Programming Language :: C++
|
||||
Programming Language :: Python :: 3 :: Only
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
Programming Language :: Python :: 3.9
|
||||
Programming Language :: Python :: 3.10
|
||||
Programming Language :: Python :: 3.11
|
||||
Programming Language :: Python :: 3.12
|
||||
Programming Language :: Python :: 3.13
|
||||
License :: OSI Approved :: BSD License
|
||||
Programming Language :: Python :: Implementation :: PyPy
|
||||
Programming Language :: Python :: Implementation :: CPython
|
||||
@ -39,5 +39,5 @@ project_urls =
|
||||
Chat = https://gitter.im/pybind/Lobby
|
||||
|
||||
[options]
|
||||
python_requires = >=3.6
|
||||
python_requires = >=3.7
|
||||
zip_safe = False
|
||||
|
15
setup.py
15
setup.py
@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Setup script for PyPI; use CMakeFile.txt to build extension modules
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
@ -9,9 +10,9 @@ import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Dict, Iterator, List, Union
|
||||
|
||||
import setuptools.command.sdist
|
||||
|
||||
@ -23,7 +24,7 @@ VERSION_FILE = Path("pybind11/_version.py")
|
||||
COMMON_FILE = Path("include/pybind11/detail/common.h")
|
||||
|
||||
|
||||
def build_expected_version_hex(matches: Dict[str, str]) -> str:
|
||||
def build_expected_version_hex(matches: dict[str, str]) -> str:
|
||||
patch_level_serial = matches["PATCH"]
|
||||
serial = None
|
||||
major = int(matches["MAJOR"])
|
||||
@ -64,7 +65,7 @@ to_src = (
|
||||
|
||||
|
||||
# Read the listed version
|
||||
loc: Dict[str, str] = {}
|
||||
loc: dict[str, str] = {}
|
||||
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
|
||||
exec(code, loc)
|
||||
version = loc["__version__"]
|
||||
@ -84,9 +85,7 @@ if version_hex != exp_version_hex:
|
||||
|
||||
|
||||
# TODO: use literals & overload (typing extensions or Python 3.8)
|
||||
def get_and_replace(
|
||||
filename: Path, binary: bool = False, **opts: str
|
||||
) -> Union[bytes, str]:
|
||||
def get_and_replace(filename: Path, binary: bool = False, **opts: str) -> bytes | str:
|
||||
if binary:
|
||||
contents = filename.read_bytes()
|
||||
return string.Template(contents.decode()).substitute(opts).encode()
|
||||
@ -97,7 +96,7 @@ def get_and_replace(
|
||||
# Use our input files instead when making the SDist (and anything that depends
|
||||
# on it, like a wheel)
|
||||
class SDist(setuptools.command.sdist.sdist):
|
||||
def make_release_tree(self, base_dir: str, files: List[str]) -> None:
|
||||
def make_release_tree(self, base_dir: str, files: list[str]) -> None:
|
||||
super().make_release_tree(base_dir, files)
|
||||
|
||||
for to, src in to_src:
|
||||
@ -112,7 +111,7 @@ class SDist(setuptools.command.sdist.sdist):
|
||||
|
||||
# Remove the CMake install directory when done
|
||||
@contextlib.contextmanager
|
||||
def remove_output(*sources: str) -> Iterator[None]:
|
||||
def remove_output(*sources: str) -> Generator[None, None, None]:
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
|
@ -7,13 +7,13 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
# Filter out items; print an optional message if any items filtered. This ignores extensions.
|
||||
@ -330,7 +330,7 @@ if(Boost_FOUND)
|
||||
add_library(Boost::headers IMPORTED INTERFACE)
|
||||
if(TARGET Boost::boost)
|
||||
# Classic FindBoost
|
||||
set_property(TARGET Boost::boost PROPERTY INTERFACE_LINK_LIBRARIES Boost::boost)
|
||||
set_property(TARGET Boost::headers PROPERTY INTERFACE_LINK_LIBRARIES Boost::boost)
|
||||
else()
|
||||
# Very old FindBoost, or newer Boost than CMake in older CMakes
|
||||
set_property(TARGET Boost::headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
|
||||
|
@ -4,6 +4,8 @@ Extends output capture as needed by pybind11: ignore constructors, optional unor
|
||||
Adds docstring and exceptions message sanitizers.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import difflib
|
||||
import gc
|
||||
|
@ -92,6 +92,9 @@ extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_gil_utils() {
|
||||
if (m != nullptr) {
|
||||
static_assert(sizeof(&gil_acquire) == sizeof(void *),
|
||||
"Function pointer must have the same size as void*");
|
||||
#ifdef Py_GIL_DISABLED
|
||||
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
||||
#endif
|
||||
ADD_FUNCTION("gil_acquire_funcaddr", gil_acquire)
|
||||
ADD_FUNCTION("gil_multi_acquire_release_funcaddr", gil_multi_acquire_release)
|
||||
ADD_FUNCTION("gil_acquire_inner_custom_funcaddr",
|
||||
|
@ -42,6 +42,9 @@ extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_interleaved_error_alrea
|
||||
if (m != nullptr) {
|
||||
static_assert(sizeof(&interleaved_error_already_set) == sizeof(void *),
|
||||
"Function pointer must have the same size as void *");
|
||||
#ifdef Py_GIL_DISABLED
|
||||
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
||||
#endif
|
||||
PyModule_AddObject(
|
||||
m,
|
||||
"funcaddr",
|
||||
|
@ -11,4 +11,6 @@
|
||||
|
||||
#include "test_eigen_tensor.inl"
|
||||
|
||||
PYBIND11_MODULE(eigen_tensor_avoid_stl_array, m) { eigen_tensor_test::test_module(m); }
|
||||
PYBIND11_MODULE(eigen_tensor_avoid_stl_array, m, pybind11::mod_gil_not_used()) {
|
||||
eigen_tensor_test::test_module(m);
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
import pytest
|
||||
|
||||
@ -9,6 +12,7 @@ WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
|
||||
|
||||
CPYTHON = platform.python_implementation() == "CPython"
|
||||
PYPY = platform.python_implementation() == "PyPy"
|
||||
PY_GIL_DISABLED = bool(sysconfig.get_config_var("Py_GIL_DISABLED"))
|
||||
|
||||
|
||||
def deprecated_call():
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import string
|
||||
@ -73,6 +75,7 @@ cmake_files = {
|
||||
"share/cmake/pybind11/pybind11Common.cmake",
|
||||
"share/cmake/pybind11/pybind11Config.cmake",
|
||||
"share/cmake/pybind11/pybind11ConfigVersion.cmake",
|
||||
"share/cmake/pybind11/pybind11GuessPythonExtSuffix.cmake",
|
||||
"share/cmake/pybind11/pybind11NewTools.cmake",
|
||||
"share/cmake/pybind11/pybind11Targets.cmake",
|
||||
"share/cmake/pybind11/pybind11Tools.cmake",
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
PYBIND11_MODULE(pybind11_cross_module_tests, m, py::mod_gil_not_used()) {
|
||||
m.doc() = "pybind11 cross-module test module";
|
||||
|
||||
// test_local_bindings.py tests:
|
||||
|
@ -58,7 +58,7 @@ void bind_ConstructorStats(py::module_ &m) {
|
||||
// registered instances to allow instance cleanup checks (invokes a GC first)
|
||||
.def_static("detail_reg_inst", []() {
|
||||
ConstructorStats::gc();
|
||||
return py::detail::get_internals().registered_instances.size();
|
||||
return py::detail::num_registered_instances();
|
||||
});
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ const char *cpp_std() {
|
||||
#endif
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(pybind11_tests, m) {
|
||||
PYBIND11_MODULE(pybind11_tests, m, py::mod_gil_not_used()) {
|
||||
m.doc() = "pybind11 test module";
|
||||
|
||||
// Intentionally kept minimal to not create a maintenance chore
|
||||
@ -89,6 +89,8 @@ PYBIND11_MODULE(pybind11_tests, m) {
|
||||
#endif
|
||||
m.attr("cpp_std") = cpp_std();
|
||||
m.attr("PYBIND11_INTERNALS_ID") = PYBIND11_INTERNALS_ID;
|
||||
// Free threaded Python uses UINT32_MAX for immortal objects.
|
||||
m.attr("PYBIND11_REFCNT_IMMORTAL") = UINT32_MAX;
|
||||
m.attr("PYBIND11_SIMPLE_GIL_MANAGEMENT") =
|
||||
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
true;
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <pybind11/eval.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace pybind11::literals;
|
||||
|
||||
@ -52,6 +54,17 @@ union IntFloat {
|
||||
float f;
|
||||
};
|
||||
|
||||
class UnusualOpRef {
|
||||
public:
|
||||
using NonTrivialType = std::shared_ptr<int>; // Almost any non-trivial type will do.
|
||||
// Overriding operator& should not break pybind11.
|
||||
NonTrivialType operator&() { return non_trivial_member; }
|
||||
NonTrivialType operator&() const { return non_trivial_member; }
|
||||
|
||||
private:
|
||||
NonTrivialType non_trivial_member;
|
||||
};
|
||||
|
||||
/// Custom cast-only type that casts to a string "rvalue" or "lvalue" depending on the cast
|
||||
/// context. Used to test recursive casters (e.g. std::tuple, stl containers).
|
||||
struct RValueCaster {};
|
||||
|
@ -20,3 +20,4 @@ filterwarnings =
|
||||
# bogus numpy ABI warning (see numpy/#432)
|
||||
ignore:.*numpy.dtype size changed.*:RuntimeWarning
|
||||
ignore:.*numpy.ufunc size changed.*:RuntimeWarning
|
||||
default:The global interpreter lock:RuntimeWarning
|
||||
|
@ -1,15 +1,13 @@
|
||||
--only-binary=:all:
|
||||
build~=0.9; python_version=="3.6"
|
||||
build~=1.0; python_version>="3.7"
|
||||
numpy~=1.20.0; python_version=="3.7" and platform_python_implementation=="PyPy"
|
||||
numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
|
||||
numpy~=1.25.0; python_version=="3.9" and platform_python_implementation=='PyPy'
|
||||
numpy~=1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
|
||||
numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10"
|
||||
numpy~=1.22.2; platform_python_implementation!="PyPy" and python_version=="3.10"
|
||||
numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13"
|
||||
pytest~=7.0
|
||||
pytest-timeout
|
||||
scipy~=1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10"
|
||||
scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10"
|
||||
scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13"
|
||||
scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10" and sys_platform!='win32'
|
||||
scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" and sys_platform!='win32'
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
asyncio = pytest.importorskip("asyncio")
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import ctypes
|
||||
import io
|
||||
import struct
|
||||
|
@ -104,9 +104,8 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
m.def("good_utf16_string", [=]() {
|
||||
return std::u16string({b16, ib16, cake16_1, cake16_2, mathbfA16_1, mathbfA16_2, z16});
|
||||
}); // b‽🎂𝐀z
|
||||
m.def("good_utf32_string", [=]() {
|
||||
return std::u32string({a32, mathbfA32, cake32, ib32, z32});
|
||||
}); // a𝐀🎂‽z
|
||||
m.def("good_utf32_string",
|
||||
[=]() { return std::u32string({a32, mathbfA32, cake32, ib32, z32}); }); // a𝐀🎂‽z
|
||||
m.def("good_wchar_string", [=]() { return wstr; }); // a‽𝐀z
|
||||
m.def("bad_utf8_string", []() {
|
||||
return std::string("abc\xd0"
|
||||
@ -117,9 +116,8 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
// UnicodeDecodeError
|
||||
m.def("bad_utf32_string", [=]() { return std::u32string({a32, char32_t(0xd800), z32}); });
|
||||
if (sizeof(wchar_t) == 2) {
|
||||
m.def("bad_wchar_string", [=]() {
|
||||
return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
|
||||
});
|
||||
m.def("bad_wchar_string",
|
||||
[=]() { return std::wstring({wchar_t(0x61), wchar_t(0xd800)}); });
|
||||
}
|
||||
m.def("u8_Z", []() -> char { return 'Z'; });
|
||||
m.def("u8_eacute", []() -> char { return '\xe9'; });
|
||||
@ -236,8 +234,7 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
|
||||
// test_int_convert
|
||||
m.def("int_passthrough", [](int arg) { return arg; });
|
||||
m.def(
|
||||
"int_passthrough_noconvert", [](int arg) { return arg; }, py::arg{}.noconvert());
|
||||
m.def("int_passthrough_noconvert", [](int arg) { return arg; }, py::arg{}.noconvert());
|
||||
|
||||
// test_tuple
|
||||
m.def(
|
||||
@ -302,8 +299,7 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
|
||||
// test_bool_caster
|
||||
m.def("bool_passthrough", [](bool arg) { return arg; });
|
||||
m.def(
|
||||
"bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg{}.noconvert());
|
||||
m.def("bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg{}.noconvert());
|
||||
|
||||
// TODO: This should be disabled and fixed in future Intel compilers
|
||||
#if !defined(__INTEL_COMPILER)
|
||||
@ -311,8 +307,7 @@ TEST_SUBMODULE(builtin_casters, m) {
|
||||
// When compiled with the Intel compiler, this results in segmentation faults when importing
|
||||
// the module. Tested with icc (ICC) 2021.1 Beta 20200827, this should be tested again when
|
||||
// a newer version of icc is available.
|
||||
m.def(
|
||||
"bool_passthrough_noconvert2", [](bool arg) { return arg; }, py::arg().noconvert());
|
||||
m.def("bool_passthrough_noconvert2", [](bool arg) { return arg; }, py::arg().noconvert());
|
||||
#endif
|
||||
|
||||
// test_reference_wrapper
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
@ -63,10 +63,8 @@ TEST_SUBMODULE(call_policies, m) {
|
||||
.def("returnNullChildKeepAliveParent", &Parent::returnNullChild, py::keep_alive<0, 1>())
|
||||
.def_static("staticFunction", &Parent::staticFunction, py::keep_alive<1, 0>());
|
||||
|
||||
m.def(
|
||||
"free_function", [](Parent *, Child *) {}, py::keep_alive<1, 2>());
|
||||
m.def(
|
||||
"invalid_arg_index", [] {}, py::keep_alive<0, 1>());
|
||||
m.def("free_function", [](Parent *, Child *) {}, py::keep_alive<1, 2>());
|
||||
m.def("invalid_arg_index", [] {}, py::keep_alive<0, 1>());
|
||||
|
||||
#if !defined(PYPY_VERSION)
|
||||
// test_alive_gc
|
||||
@ -97,7 +95,7 @@ TEST_SUBMODULE(call_policies, m) {
|
||||
},
|
||||
py::call_guard<DependentGuard, CustomGuard>());
|
||||
|
||||
#if defined(WITH_THREAD) && !defined(PYPY_VERSION)
|
||||
#if !defined(PYPY_VERSION)
|
||||
// `py::call_guard<py::gil_scoped_release>()` should work in PyPy as well,
|
||||
// but it's unclear how to test it without `PyGILState_GetThisThreadState`.
|
||||
auto report_gil_status = []() {
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
import env # noqa: F401
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from threading import Thread
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import datetime
|
||||
|
||||
import pytest
|
||||
|
@ -403,7 +403,7 @@ TEST_SUBMODULE(class_, m) {
|
||||
// [workaround(intel)] = default does not work here
|
||||
// Removing or defaulting this destructor results in linking errors with the Intel compiler
|
||||
// (in Debug builds only, tested with icpc (ICC) 2021.1 Beta 20200827)
|
||||
~PublicistB() override{}; // NOLINT(modernize-use-equals-default)
|
||||
~PublicistB() override {}; // NOLINT(modernize-use-equals-default)
|
||||
using ProtectedB::foo;
|
||||
using ProtectedB::get_self;
|
||||
using ProtectedB::void_foo;
|
||||
@ -461,8 +461,7 @@ TEST_SUBMODULE(class_, m) {
|
||||
py::class_<Nested>(base, "Nested")
|
||||
.def(py::init<>())
|
||||
.def("fn", [](Nested &, int, NestBase &, Nested &) {})
|
||||
.def(
|
||||
"fa", [](Nested &, int, NestBase &, Nested &) {}, "a"_a, "b"_a, "c"_a);
|
||||
.def("fa", [](Nested &, int, NestBase &, Nested &) {}, "a"_a, "b"_a, "c"_a);
|
||||
base.def("g", [](NestBase &, Nested &) {});
|
||||
base.def("h", []() { return NestBase(); });
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
||||
import env
|
||||
from pybind11_tests import ConstructorStats, UserType
|
||||
from pybind11_tests import PYBIND11_REFCNT_IMMORTAL, ConstructorStats, UserType
|
||||
from pybind11_tests import class_ as m
|
||||
|
||||
|
||||
@ -377,7 +379,9 @@ def test_class_refcount():
|
||||
refcount_3 = getrefcount(cls)
|
||||
|
||||
assert refcount_1 == refcount_3
|
||||
assert refcount_2 > refcount_1
|
||||
assert (refcount_2 > refcount_1) or (
|
||||
refcount_2 == refcount_1 == PYBIND11_REFCNT_IMMORTAL
|
||||
)
|
||||
|
||||
|
||||
def test_reentrant_implicit_conversion_failure(msg):
|
||||
|
@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
project(test_installed_embed CXX)
|
||||
|
@ -1,13 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(test_installed_module CXX)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
project(test_installed_function CXX)
|
||||
|
@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
project(test_installed_target CXX)
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <pybind11/pybind11.h>
|
||||
namespace py = pybind11;
|
||||
|
||||
PYBIND11_MODULE(test_cmake_build, m) {
|
||||
PYBIND11_MODULE(test_cmake_build, m, py::mod_gil_not_used()) {
|
||||
m.def("add", [](int i, int j) { return i + j; });
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
project(test_subdirectory_embed CXX)
|
||||
|
@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
project(test_subdirectory_function CXX)
|
||||
|
@ -1,12 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.27)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.5...3.29)` syntax does not work with
|
||||
# some versions of VS that have a patched CMake 3.11. This forces us to emulate
|
||||
# the behavior using the following workaround:
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.27)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.29)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.27)
|
||||
cmake_policy(VERSION 3.29)
|
||||
endif()
|
||||
|
||||
project(test_subdirectory_target CXX)
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import test_cmake_build
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import const_name as m
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
m = pytest.importorskip("pybind11_tests.constants_and_functions")
|
||||
|
@ -157,6 +157,13 @@ public:
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(pybind11)
|
||||
|
||||
namespace {
|
||||
|
||||
py::object CastUnusualOpRefConstRef(const UnusualOpRef &cref) { return py::cast(cref); }
|
||||
py::object CastUnusualOpRefMovable(UnusualOpRef &&mvbl) { return py::cast(std::move(mvbl)); }
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST_SUBMODULE(copy_move_policies, m) {
|
||||
// test_lacking_copy_ctor
|
||||
py::class_<lacking_copy_ctor>(m, "lacking_copy_ctor")
|
||||
@ -289,11 +296,15 @@ TEST_SUBMODULE(copy_move_policies, m) {
|
||||
"get_moveissue1",
|
||||
[](int i) { return std::unique_ptr<MoveIssue1>(new MoveIssue1(i)); },
|
||||
py::return_value_policy::move);
|
||||
m.def(
|
||||
"get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
|
||||
m.def("get_moveissue2", [](int i) { return MoveIssue2(i); }, py::return_value_policy::move);
|
||||
|
||||
// Make sure that cast from pytype rvalue to other pytype works
|
||||
m.def("get_pytype_rvalue_castissue", [](double i) { return py::float_(i).cast<py::int_>(); });
|
||||
|
||||
py::class_<UnusualOpRef>(m, "UnusualOpRef");
|
||||
m.def("CallCastUnusualOpRefConstRef",
|
||||
[]() { return CastUnusualOpRefConstRef(UnusualOpRef()); });
|
||||
m.def("CallCastUnusualOpRefMovable", []() { return CastUnusualOpRefMovable(UnusualOpRef()); });
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import copy_move_policies as m
|
||||
@ -130,3 +132,9 @@ def test_pytype_rvalue_cast():
|
||||
|
||||
value = m.get_pytype_rvalue_castissue(1.0)
|
||||
assert value == 1
|
||||
|
||||
|
||||
def test_unusual_op_ref():
|
||||
# Merely to test that this still exists and built successfully.
|
||||
assert m.CallCastUnusualOpRefConstRef().__class__.__name__ == "UnusualOpRef"
|
||||
assert m.CallCastUnusualOpRefMovable().__class__.__name__ == "UnusualOpRef"
|
||||
|
@ -185,14 +185,10 @@ TEST_SUBMODULE(custom_type_casters, m) {
|
||||
py::arg_v(nullptr, ArgInspector1()).noconvert(true),
|
||||
py::arg() = ArgAlwaysConverts());
|
||||
|
||||
m.def(
|
||||
"floats_preferred", [](double f) { return 0.5 * f; }, "f"_a);
|
||||
m.def(
|
||||
"floats_only", [](double f) { return 0.5 * f; }, "f"_a.noconvert());
|
||||
m.def(
|
||||
"ints_preferred", [](int i) { return i / 2; }, "i"_a);
|
||||
m.def(
|
||||
"ints_only", [](int i) { return i / 2; }, "i"_a.noconvert());
|
||||
m.def("floats_preferred", [](double f) { return 0.5 * f; }, "f"_a);
|
||||
m.def("floats_only", [](double f) { return 0.5 * f; }, "f"_a.noconvert());
|
||||
m.def("ints_preferred", [](int i) { return i / 2; }, "i"_a);
|
||||
m.def("ints_only", [](int i) { return i / 2; }, "i"_a.noconvert());
|
||||
|
||||
// test_custom_caster_destruction
|
||||
// Test that `take_ownership` works on types with a custom type caster when given a pointer
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import custom_type_casters as m
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import gc
|
||||
import weakref
|
||||
|
||||
|
@ -15,37 +15,26 @@ TEST_SUBMODULE(docstring_options, m) {
|
||||
py::options options;
|
||||
options.disable_function_signatures();
|
||||
|
||||
m.def(
|
||||
"test_function1", [](int, int) {}, py::arg("a"), py::arg("b"));
|
||||
m.def(
|
||||
"test_function2", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
m.def("test_function1", [](int, int) {}, py::arg("a"), py::arg("b"));
|
||||
m.def("test_function2", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
|
||||
m.def(
|
||||
"test_overloaded1", [](int) {}, py::arg("i"), "Overload docstring");
|
||||
m.def(
|
||||
"test_overloaded1", [](double) {}, py::arg("d"));
|
||||
m.def("test_overloaded1", [](int) {}, py::arg("i"), "Overload docstring");
|
||||
m.def("test_overloaded1", [](double) {}, py::arg("d"));
|
||||
|
||||
m.def(
|
||||
"test_overloaded2", [](int) {}, py::arg("i"), "overload docstring 1");
|
||||
m.def(
|
||||
"test_overloaded2", [](double) {}, py::arg("d"), "overload docstring 2");
|
||||
m.def("test_overloaded2", [](int) {}, py::arg("i"), "overload docstring 1");
|
||||
m.def("test_overloaded2", [](double) {}, py::arg("d"), "overload docstring 2");
|
||||
|
||||
m.def(
|
||||
"test_overloaded3", [](int) {}, py::arg("i"));
|
||||
m.def(
|
||||
"test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr");
|
||||
m.def("test_overloaded3", [](int) {}, py::arg("i"));
|
||||
m.def("test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr");
|
||||
|
||||
options.enable_function_signatures();
|
||||
|
||||
m.def(
|
||||
"test_function3", [](int, int) {}, py::arg("a"), py::arg("b"));
|
||||
m.def(
|
||||
"test_function4", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
m.def("test_function3", [](int, int) {}, py::arg("a"), py::arg("b"));
|
||||
m.def("test_function4", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
|
||||
options.disable_function_signatures().disable_user_defined_docstrings();
|
||||
|
||||
m.def(
|
||||
"test_function5", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
m.def("test_function5", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
|
||||
{
|
||||
py::options nested_options;
|
||||
@ -59,8 +48,7 @@ TEST_SUBMODULE(docstring_options, m) {
|
||||
}
|
||||
}
|
||||
|
||||
m.def(
|
||||
"test_function7", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
m.def("test_function7", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||
|
||||
{
|
||||
py::options options;
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pybind11_tests import docstring_options as m
|
||||
|
||||
|
||||
|
@ -340,12 +340,10 @@ TEST_SUBMODULE(eigen_matrix, m) {
|
||||
if (have_numpy) {
|
||||
py::module_::import("numpy");
|
||||
Eigen::Matrix<double, 3, 3> defaultMatrix = Eigen::Matrix3d::Identity();
|
||||
m.def(
|
||||
"defaults_mat", [](const Eigen::Matrix3d &) {}, py::arg("mat") = defaultMatrix);
|
||||
m.def("defaults_mat", [](const Eigen::Matrix3d &) {}, py::arg("mat") = defaultMatrix);
|
||||
|
||||
Eigen::VectorXd defaultVector = Eigen::VectorXd::Ones(32);
|
||||
m.def(
|
||||
"defaults_vec", [](const Eigen::VectorXd &) {}, py::arg("vec") = defaultMatrix);
|
||||
m.def("defaults_vec", [](const Eigen::VectorXd &) {}, py::arg("vec") = defaultMatrix);
|
||||
}
|
||||
// test_sparse, test_sparse_signature
|
||||
m.def("sparse_r", [mat]() -> SparseMatrixR {
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import ConstructorStats
|
||||
|
@ -121,8 +121,7 @@ void init_tensor_module(pybind11::module &m) {
|
||||
[]() { return &get_fixed_tensor<Options>(); },
|
||||
py::return_value_policy::copy);
|
||||
|
||||
m.def(
|
||||
"copy_tensor", []() { return &get_tensor<Options>(); }, py::return_value_policy::copy);
|
||||
m.def("copy_tensor", []() { return &get_tensor<Options>(); }, py::return_value_policy::copy);
|
||||
|
||||
m.def(
|
||||
"copy_const_tensor",
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
@ -7,6 +7,13 @@ if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STR
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(TARGET Python::Module AND NOT TARGET Python::Python)
|
||||
message(STATUS "Skipping embed test since no embed libs found")
|
||||
add_custom_target(cpptest) # Dummy target since embedding is not supported.
|
||||
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
find_package(Catch 2.13.9)
|
||||
|
||||
if(CATCH_FOUND)
|
||||
|
@ -6,7 +6,7 @@ namespace py = pybind11;
|
||||
* modules aren't preserved over a finalize/initialize.
|
||||
*/
|
||||
|
||||
PYBIND11_MODULE(external_module, m) {
|
||||
PYBIND11_MODULE(external_module, m, py::mod_gil_not_used()) {
|
||||
class A {
|
||||
public:
|
||||
explicit A(int value) : v{value} {};
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
from widget_module import Widget
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import trampoline_module
|
||||
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
# ruff: noqa: SIM201 SIM300 SIM202
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
||||
import pytest
|
||||
|
@ -1,4 +1,5 @@
|
||||
# This file is called from 'test_eval.py'
|
||||
from __future__ import annotations
|
||||
|
||||
if "call_test2" in locals():
|
||||
call_test2(y) # noqa: F821 undefined name
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import multiprocessing
|
||||
import sys
|
||||
import threading
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from contextlib import redirect_stderr, redirect_stdout
|
||||
from io import StringIO
|
||||
|
||||
@ -34,7 +36,7 @@ def test_captured_large_string(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_2byte_offset0(capsys):
|
||||
msg = "\u07FF"
|
||||
msg = "\u07ff"
|
||||
msg = "" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -44,7 +46,7 @@ def test_captured_utf8_2byte_offset0(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_2byte_offset1(capsys):
|
||||
msg = "\u07FF"
|
||||
msg = "\u07ff"
|
||||
msg = "1" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -54,7 +56,7 @@ def test_captured_utf8_2byte_offset1(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_3byte_offset0(capsys):
|
||||
msg = "\uFFFF"
|
||||
msg = "\uffff"
|
||||
msg = "" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -64,7 +66,7 @@ def test_captured_utf8_3byte_offset0(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_3byte_offset1(capsys):
|
||||
msg = "\uFFFF"
|
||||
msg = "\uffff"
|
||||
msg = "1" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -74,7 +76,7 @@ def test_captured_utf8_3byte_offset1(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_3byte_offset2(capsys):
|
||||
msg = "\uFFFF"
|
||||
msg = "\uffff"
|
||||
msg = "12" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -84,7 +86,7 @@ def test_captured_utf8_3byte_offset2(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_4byte_offset0(capsys):
|
||||
msg = "\U0010FFFF"
|
||||
msg = "\U0010ffff"
|
||||
msg = "" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -94,7 +96,7 @@ def test_captured_utf8_4byte_offset0(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_4byte_offset1(capsys):
|
||||
msg = "\U0010FFFF"
|
||||
msg = "\U0010ffff"
|
||||
msg = "1" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -104,7 +106,7 @@ def test_captured_utf8_4byte_offset1(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_4byte_offset2(capsys):
|
||||
msg = "\U0010FFFF"
|
||||
msg = "\U0010ffff"
|
||||
msg = "12" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
@ -114,7 +116,7 @@ def test_captured_utf8_4byte_offset2(capsys):
|
||||
|
||||
|
||||
def test_captured_utf8_4byte_offset3(capsys):
|
||||
msg = "\U0010FFFF"
|
||||
msg = "\U0010ffff"
|
||||
msg = "123" + msg * (1024 // len(msg) + 1)
|
||||
|
||||
m.captured_output_default(msg)
|
||||
|
@ -22,8 +22,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
m.def("kw_func0", kw_func);
|
||||
m.def("kw_func1", kw_func, py::arg("x"), py::arg("y"));
|
||||
m.def("kw_func2", kw_func, py::arg("x") = 100, py::arg("y") = 200);
|
||||
m.def(
|
||||
"kw_func3", [](const char *) {}, py::arg("data") = std::string("Hello world!"));
|
||||
m.def("kw_func3", [](const char *) {}, py::arg("data") = std::string("Hello world!"));
|
||||
|
||||
/* A fancier default argument */
|
||||
std::vector<int> list{{13, 17}};
|
||||
@ -79,14 +78,12 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
"kw_lb_func5",
|
||||
[](const CustomRepr &) {},
|
||||
py::arg("custom") = CustomRepr("array([[A, B],\r [C, D]])"));
|
||||
m.def(
|
||||
"kw_lb_func6", [](const CustomRepr &) {}, py::arg("custom") = CustomRepr(" \v\t "));
|
||||
m.def("kw_lb_func6", [](const CustomRepr &) {}, py::arg("custom") = CustomRepr(" \v\t "));
|
||||
m.def(
|
||||
"kw_lb_func7",
|
||||
[](const std::string &) {},
|
||||
py::arg("str_arg") = "First line.\n Second line.");
|
||||
m.def(
|
||||
"kw_lb_func8", [](const CustomRepr &) {}, py::arg("custom") = CustomRepr(""));
|
||||
m.def("kw_lb_func8", [](const CustomRepr &) {}, py::arg("custom") = CustomRepr(""));
|
||||
|
||||
// test_args_and_kwargs
|
||||
m.def("args_function", [](py::args args) -> py::tuple {
|
||||
@ -153,10 +150,13 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
|
||||
// test_args_refcount
|
||||
// PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
|
||||
// PyPy uses the top few bits for REFCNT_FROM_PYPY & REFCNT_FROM_PYPY_LIGHT, so truncate
|
||||
#ifdef PYPY_VERSION
|
||||
# define GC_IF_NEEDED ConstructorStats::gc()
|
||||
# define REFCNT(x) (int) Py_REFCNT(x)
|
||||
#else
|
||||
# define GC_IF_NEEDED
|
||||
# define REFCNT(x) Py_REFCNT(x)
|
||||
#endif
|
||||
m.def("arg_refcount_h", [](py::handle h) {
|
||||
GC_IF_NEEDED;
|
||||
@ -175,7 +175,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
py::tuple t(a.size());
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
// Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
|
||||
t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
|
||||
t[i] = REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
|
||||
}
|
||||
return t;
|
||||
});
|
||||
@ -185,7 +185,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
t[0] = o.ref_count();
|
||||
for (size_t i = 0; i < a.size(); i++) {
|
||||
// Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
|
||||
t[i + 1] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
|
||||
t[i + 1] = REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
|
||||
}
|
||||
return t;
|
||||
});
|
||||
@ -279,11 +279,9 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
|
||||
// These should fail to compile:
|
||||
#ifdef PYBIND11_NEVER_DEFINED_EVER
|
||||
// argument annotations are required when using kw_only
|
||||
m.def(
|
||||
"bad_kw_only1", [](int) {}, py::kw_only());
|
||||
m.def("bad_kw_only1", [](int) {}, py::kw_only());
|
||||
// can't specify both `py::kw_only` and a `py::args` argument
|
||||
m.def(
|
||||
"bad_kw_only2", [](int i, py::args) {}, py::kw_only(), "i"_a);
|
||||
m.def("bad_kw_only2", [](int i, py::args) {}, py::kw_only(), "i"_a);
|
||||
#endif
|
||||
|
||||
// test_function_signatures (along with most of the above)
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from pybind11_tests import kwargs_and_defaults as m
|
||||
@ -381,7 +383,7 @@ def test_args_refcount():
|
||||
arguments"""
|
||||
refcount = m.arg_refcount_h
|
||||
|
||||
myval = 54321
|
||||
myval = object()
|
||||
expected = refcount(myval)
|
||||
assert m.arg_refcount_h(myval) == expected
|
||||
assert m.arg_refcount_o(myval) == expected + 1
|
||||
@ -420,6 +422,7 @@ def test_args_refcount():
|
||||
# for the `py::args`; in the previous case, we could simply inc_ref and pass on Python's input
|
||||
# tuple without having to inc_ref the individual elements, but here we can't, hence the extra
|
||||
# refs.
|
||||
assert m.mixed_args_refcount(myval, myval, myval) == (exp3 + 3, exp3 + 3, exp3 + 3)
|
||||
exp3_3 = exp3 + 3
|
||||
assert m.mixed_args_refcount(myval, myval, myval) == (exp3_3, exp3_3, exp3_3)
|
||||
|
||||
assert m.class_default_argument() == "<class 'decimal.Decimal'>"
|
||||
|
@ -1,3 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
import env # noqa: F401
|
||||
|
@ -374,8 +374,7 @@ TEST_SUBMODULE(methods_and_attributes, m) {
|
||||
m.def("overload_order", [](const std::string &) { return 1; });
|
||||
m.def("overload_order", [](const std::string &) { return 2; });
|
||||
m.def("overload_order", [](int) { return 3; });
|
||||
m.def(
|
||||
"overload_order", [](int) { return 4; }, py::prepend{});
|
||||
m.def("overload_order", [](int) { return 4; }, py::prepend{});
|
||||
|
||||
#if !defined(PYPY_VERSION)
|
||||
// test_dynamic_attributes
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user