3rdparty: Bump vendored pybind11 version for py3.11 support
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
f1349e114f
commit
a72f898ff4
8
3rdparty/pybind11/.appveyor.yml
vendored
8
3rdparty/pybind11/.appveyor.yml
vendored
@ -1,6 +1,6 @@
|
||||
version: 1.0.{build}
|
||||
image:
|
||||
- Visual Studio 2015
|
||||
- Visual Studio 2017
|
||||
test: off
|
||||
skip_branch_with_pr: true
|
||||
build:
|
||||
@ -11,15 +11,13 @@ environment:
|
||||
matrix:
|
||||
- PYTHON: 36
|
||||
CONFIG: Debug
|
||||
- PYTHON: 27
|
||||
CONFIG: Debug
|
||||
install:
|
||||
- ps: |
|
||||
$env:CMAKE_GENERATOR = "Visual Studio 14 2015"
|
||||
$env:CMAKE_GENERATOR = "Visual Studio 15 2017"
|
||||
if ($env:PLATFORM -eq "x64") { $env:PYTHON = "$env:PYTHON-x64" }
|
||||
$env:PATH = "C:\Python$env:PYTHON\;C:\Python$env:PYTHON\Scripts\;$env:PATH"
|
||||
python -W ignore -m pip install --upgrade pip wheel
|
||||
python -W ignore -m pip install pytest numpy --no-warn-script-location
|
||||
python -W ignore -m pip install pytest numpy --no-warn-script-location pytest-timeout
|
||||
- ps: |
|
||||
Start-FileDownload 'https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.zip'
|
||||
7z x eigen-3.3.7.zip -y > $null
|
||||
|
38
3rdparty/pybind11/.clang-format
vendored
Normal file
38
3rdparty/pybind11/.clang-format
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
---
|
||||
# See all possible options and defaults with:
|
||||
# clang-format --style=llvm --dump-config
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AllowShortLambdasOnASingleLine: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakConstructorInitializers: BeforeColon
|
||||
ColumnLimit: 99
|
||||
CommentPragmas: 'NOLINT:.*|^ IWYU pragma:'
|
||||
IncludeBlocks: Regroup
|
||||
IndentCaseLabels: true
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
Language: Cpp
|
||||
SpaceAfterCStyleCast: true
|
||||
Standard: Cpp11
|
||||
StatementMacros: ['PyObject_HEAD']
|
||||
TabWidth: 4
|
||||
IncludeCategories:
|
||||
- Regex: '<pybind11/.*'
|
||||
Priority: -1
|
||||
- Regex: 'pybind11.h"$'
|
||||
Priority: 1
|
||||
- Regex: '^".*/?detail/'
|
||||
Priority: 1
|
||||
SortPriority: 2
|
||||
- Regex: '^"'
|
||||
Priority: 1
|
||||
SortPriority: 3
|
||||
- Regex: '<[[:alnum:]._]+>'
|
||||
Priority: 4
|
||||
- Regex: '.*'
|
||||
Priority: 5
|
||||
...
|
82
3rdparty/pybind11/.clang-tidy
vendored
82
3rdparty/pybind11/.clang-tidy
vendored
@ -1,13 +1,77 @@
|
||||
FormatStyle: file
|
||||
|
||||
Checks: '
|
||||
llvm-namespace-comment,
|
||||
modernize-use-override,
|
||||
readability-container-size-empty,
|
||||
modernize-use-using,
|
||||
modernize-use-equals-default,
|
||||
modernize-use-auto,
|
||||
modernize-use-emplace,
|
||||
'
|
||||
Checks: |
|
||||
*bugprone*,
|
||||
*performance*,
|
||||
clang-analyzer-optin.cplusplus.VirtualCall,
|
||||
clang-analyzer-optin.performance.Padding,
|
||||
cppcoreguidelines-init-variables,
|
||||
cppcoreguidelines-prefer-member-initializer,
|
||||
cppcoreguidelines-pro-type-static-cast-downcast,
|
||||
cppcoreguidelines-slicing,
|
||||
google-explicit-constructor,
|
||||
llvm-namespace-comment,
|
||||
misc-definitions-in-headers,
|
||||
misc-misplaced-const,
|
||||
misc-non-copyable-objects,
|
||||
misc-static-assert,
|
||||
misc-throw-by-value-catch-by-reference,
|
||||
misc-uniqueptr-reset-release,
|
||||
misc-unused-parameters,
|
||||
modernize-avoid-bind,
|
||||
modernize-loop-convert,
|
||||
modernize-make-shared,
|
||||
modernize-redundant-void-arg,
|
||||
modernize-replace-auto-ptr,
|
||||
modernize-replace-disallow-copy-and-assign-macro,
|
||||
modernize-replace-random-shuffle,
|
||||
modernize-shrink-to-fit,
|
||||
modernize-use-auto,
|
||||
modernize-use-bool-literals,
|
||||
modernize-use-default-member-init,
|
||||
modernize-use-emplace,
|
||||
modernize-use-equals-default,
|
||||
modernize-use-equals-delete,
|
||||
modernize-use-noexcept,
|
||||
modernize-use-nullptr,
|
||||
modernize-use-override,
|
||||
modernize-use-using,
|
||||
readability-avoid-const-params-in-decls,
|
||||
readability-braces-around-statements,
|
||||
readability-const-return-type,
|
||||
readability-container-size-empty,
|
||||
readability-delete-null-pointer,
|
||||
readability-else-after-return,
|
||||
readability-implicit-bool-conversion,
|
||||
readability-inconsistent-declaration-parameter-name,
|
||||
readability-make-member-function-const,
|
||||
readability-misplaced-array-index,
|
||||
readability-non-const-parameter,
|
||||
readability-qualified-auto,
|
||||
readability-redundant-function-ptr-dereference,
|
||||
readability-redundant-smartptr-get,
|
||||
readability-redundant-string-cstr,
|
||||
readability-simplify-subscript-expr,
|
||||
readability-static-accessed-through-instance,
|
||||
readability-static-definition-in-anonymous-namespace,
|
||||
readability-string-compare,
|
||||
readability-suspicious-call-argument,
|
||||
readability-uniqueptr-delete-release,
|
||||
-bugprone-easily-swappable-parameters,
|
||||
-bugprone-exception-escape,
|
||||
-bugprone-reserved-identifier,
|
||||
-bugprone-unused-raii,
|
||||
|
||||
CheckOptions:
|
||||
- key: modernize-use-equals-default.IgnoreMacros
|
||||
value: false
|
||||
- key: performance-for-range-copy.WarnOnAllAutoCopies
|
||||
value: true
|
||||
- key: performance-inefficient-string-concatenation.StrictMode
|
||||
value: true
|
||||
- key: performance-unnecessary-value-param.AllowedTypes
|
||||
value: 'exception_ptr$;'
|
||||
- key: readability-implicit-bool-conversion.AllowPointerConditions
|
||||
value: true
|
||||
|
||||
HeaderFilterRegex: 'pybind11/.*h'
|
||||
|
24
3rdparty/pybind11/.codespell-ignore-lines
vendored
Normal file
24
3rdparty/pybind11/.codespell-ignore-lines
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t>
|
||||
template <typename ThisT>
|
||||
auto &this_ = static_cast<ThisT &>(*this);
|
||||
if (load_impl<ThisT>(temp, false)) {
|
||||
ssize_t nd = 0;
|
||||
auto trivial = broadcast(buffers, nd, shape);
|
||||
auto ndim = (size_t) nd;
|
||||
int nd;
|
||||
ssize_t ndim() const { return detail::array_proxy(m_ptr)->nd; }
|
||||
using op = op_impl<id, ot, Base, L_type, R_type>;
|
||||
template <op_id id, op_type ot, typename L, typename R>
|
||||
template <detail::op_id id, detail::op_type ot, typename L, typename R, typename... Extra>
|
||||
class_ &def(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
|
||||
class_ &def_cast(const detail::op_<id, ot, L, R> &op, const Extra &...extra) {
|
||||
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
|
||||
struct IntStruct {
|
||||
explicit IntStruct(int v) : value(v){};
|
||||
~IntStruct() { value = -value; }
|
||||
IntStruct(const IntStruct &) = default;
|
||||
IntStruct &operator=(const IntStruct &) = default;
|
||||
py::class_<IntStruct>(m, "IntStruct").def(py::init([](const int i) { return IntStruct(i); }));
|
||||
py::implicitly_convertible<int, IntStruct>();
|
||||
m.def("test", [](int expected, const IntStruct &in) {
|
||||
[](int expected, const IntStruct &in) {
|
1
3rdparty/pybind11/.gitattributes
vendored
Normal file
1
3rdparty/pybind11/.gitattributes
vendored
Normal file
@ -0,0 +1 @@
|
||||
docs/*.svg binary
|
9
3rdparty/pybind11/.github/CODEOWNERS
vendored
Normal file
9
3rdparty/pybind11/.github/CODEOWNERS
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
*.cmake @henryiii
|
||||
CMakeLists.txt @henryiii
|
||||
*.yml @henryiii
|
||||
*.yaml @henryiii
|
||||
/tools/ @henryiii
|
||||
/pybind11/ @henryiii
|
||||
noxfile.py @henryiii
|
||||
.clang-format @henryiii
|
||||
.clang-tidy @henryiii
|
105
3rdparty/pybind11/.github/CONTRIBUTING.md
vendored
105
3rdparty/pybind11/.github/CONTRIBUTING.md
vendored
@ -53,6 +53,33 @@ derivative works thereof, in binary and source code form.
|
||||
|
||||
## Development of pybind11
|
||||
|
||||
### Quick setup
|
||||
|
||||
To setup a quick development environment, use [`nox`](https://nox.thea.codes).
|
||||
This will allow you to do some common tasks with minimal setup effort, but will
|
||||
take more time to run and be less flexible than a full development environment.
|
||||
If you use [`pipx run nox`](https://pipx.pypa.io), you don't even need to
|
||||
install `nox`. Examples:
|
||||
|
||||
```bash
|
||||
# List all available sessions
|
||||
nox -l
|
||||
|
||||
# Run linters
|
||||
nox -s lint
|
||||
|
||||
# Run tests on Python 3.9
|
||||
nox -s tests-3.9
|
||||
|
||||
# Build and preview docs
|
||||
nox -s docs -- serve
|
||||
|
||||
# Build SDists and wheels
|
||||
nox -s build
|
||||
```
|
||||
|
||||
### Full setup
|
||||
|
||||
To setup an ideal development environment, run the following commands on a
|
||||
system with CMake 3.14+:
|
||||
|
||||
@ -66,11 +93,10 @@ cmake --build build -j4
|
||||
|
||||
Tips:
|
||||
|
||||
* You can use `virtualenv` (from PyPI) instead of `venv` (which is Python 3
|
||||
only).
|
||||
* You can use `virtualenv` (faster, from PyPI) instead of `venv`.
|
||||
* You can select any name for your environment folder; if it contains "env" it
|
||||
will be ignored by git.
|
||||
* If you don’t have CMake 3.14+, just add “cmake” to the pip install command.
|
||||
* If you don't have CMake 3.14+, just add "cmake" to the pip install command.
|
||||
* You can use `-DPYBIND11_FINDPYTHON=ON` to use FindPython on CMake 3.12+
|
||||
* In classic mode, you may need to set `-DPYTHON_EXECUTABLE=/path/to/python`.
|
||||
FindPython uses `-DPython_ROOT_DIR=/path/to` or
|
||||
@ -78,7 +104,7 @@ Tips:
|
||||
|
||||
### Configuration options
|
||||
|
||||
In CMake, configuration options are given with “-D”. Options are stored in the
|
||||
In CMake, configuration options are given with "-D". Options are stored in the
|
||||
build directory, in the `CMakeCache.txt` file, so they are remembered for each
|
||||
build directory. Two selections are special - the generator, given with `-G`,
|
||||
and the compiler, which is selected based on environment variables `CXX` and
|
||||
@ -88,12 +114,12 @@ after the initial run.
|
||||
The valid options are:
|
||||
|
||||
* `-DCMAKE_BUILD_TYPE`: Release, Debug, MinSizeRel, RelWithDebInfo
|
||||
* `-DPYBIND11_FINDPYTHON=ON`: Use CMake 3.12+’s FindPython instead of the
|
||||
* `-DPYBIND11_FINDPYTHON=ON`: Use CMake 3.12+'s FindPython instead of the
|
||||
classic, deprecated, custom FindPythonLibs
|
||||
* `-DPYBIND11_NOPYTHON=ON`: Disable all Python searching (disables tests)
|
||||
* `-DBUILD_TESTING=ON`: Enable the tests
|
||||
* `-DDOWNLOAD_CATCH=ON`: Download catch to build the C++ tests
|
||||
* `-DOWNLOAD_EIGEN=ON`: Download Eigen for the NumPy tests
|
||||
* `-DDOWNLOAD_EIGEN=ON`: Download Eigen for the NumPy tests
|
||||
* `-DPYBIND11_INSTALL=ON/OFF`: Enable the install target (on by default for the
|
||||
master project)
|
||||
* `-DUSE_PYTHON_INSTALL_DIR=ON`: Try to install into the python dir
|
||||
@ -126,13 +152,26 @@ cmake --build build --target check
|
||||
`--target` can be spelled `-t` in CMake 3.15+. You can also run individual
|
||||
tests with these targets:
|
||||
|
||||
* `pytest`: Python tests only
|
||||
* `pytest`: Python tests only, using the
|
||||
[pytest](https://docs.pytest.org/en/stable/) framework
|
||||
* `cpptest`: C++ tests only
|
||||
* `test_cmake_build`: Install / subdirectory tests
|
||||
|
||||
If you want to build just a subset of tests, use
|
||||
`-DPYBIND11_TEST_OVERRIDE="test_callbacks.cpp;test_pickling.cpp"`. If this is
|
||||
empty, all tests will be built.
|
||||
`-DPYBIND11_TEST_OVERRIDE="test_callbacks;test_pickling"`. If this is
|
||||
empty, all tests will be built. Tests are specified without an extension if they need both a .py and
|
||||
.cpp file.
|
||||
|
||||
You may also pass flags to the `pytest` target by editing `tests/pytest.ini` or
|
||||
by using the `PYTEST_ADDOPTS` environment variable
|
||||
(see [`pytest` docs](https://docs.pytest.org/en/2.7.3/customize.html#adding-default-options)). As an example:
|
||||
|
||||
```bash
|
||||
env PYTEST_ADDOPTS="--capture=no --exitfirst" \
|
||||
cmake --build build --target pytest
|
||||
# Or using abbreviated flags
|
||||
env PYTEST_ADDOPTS="-s -x" cmake --build build --target pytest
|
||||
```
|
||||
|
||||
### Formatting
|
||||
|
||||
@ -164,18 +203,46 @@ name, pre-commit):
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
### Clang-Tidy
|
||||
### Clang-Format
|
||||
|
||||
To run Clang tidy, the following recipe should work. Files will be modified in
|
||||
place, so you can use git to monitor the changes.
|
||||
As of v2.6.2, pybind11 ships with a [`clang-format`][clang-format]
|
||||
configuration file at the top level of the repo (the filename is
|
||||
`.clang-format`). Currently, formatting is NOT applied automatically, but
|
||||
manually using `clang-format` for newly developed files is highly encouraged.
|
||||
To check if a file needs formatting:
|
||||
|
||||
```bash
|
||||
docker run --rm -v $PWD:/pybind11 -it silkeh/clang:10
|
||||
apt-get update && apt-get install python3-dev python3-pytest
|
||||
cmake -S pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);-fix"
|
||||
cmake --build build
|
||||
clang-format -style=file --dry-run some.cpp
|
||||
```
|
||||
|
||||
The output will show things to be fixed, if any. To actually format the file:
|
||||
|
||||
```bash
|
||||
clang-format -style=file -i some.cpp
|
||||
```
|
||||
|
||||
Note that the `-style-file` option searches the parent directories for the
|
||||
`.clang-format` file, i.e. the commands above can be run in any subdirectory
|
||||
of the pybind11 repo.
|
||||
|
||||
### Clang-Tidy
|
||||
|
||||
[`clang-tidy`][clang-tidy] performs deeper static code analyses and is
|
||||
more complex to run, compared to `clang-format`, but support for `clang-tidy`
|
||||
is built into the pybind11 CMake configuration. To run `clang-tidy`, the
|
||||
following recipe should work. Run the `docker` command from the top-level
|
||||
directory inside your pybind11 git clone. Files will be modified in place,
|
||||
so you can use git to monitor the changes.
|
||||
|
||||
```bash
|
||||
docker run --rm -v $PWD:/mounted_pybind11 -it silkeh/clang:13
|
||||
apt-get update && apt-get install -y python3-dev python3-pytest
|
||||
cmake -S /mounted_pybind11/ -B build -DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color" -DDOWNLOAD_EIGEN=ON -DDOWNLOAD_CATCH=ON -DCMAKE_CXX_STANDARD=17
|
||||
cmake --build build -j 2
|
||||
```
|
||||
|
||||
You can add `--fix` to the options list if you want.
|
||||
|
||||
### Include what you use
|
||||
|
||||
To run include what you use, install (`brew install include-what-you-use` on
|
||||
@ -186,12 +253,12 @@ cmake -S . -B build-iwyu -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE=$(which include-what-y
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
The report is sent to stderr; you can pip it into a file if you wish.
|
||||
The report is sent to stderr; you can pipe it into a file if you wish.
|
||||
|
||||
### Build recipes
|
||||
|
||||
This builds with the Intel compiler (assuming it is in your path, along with a
|
||||
recent CMake and Python 3):
|
||||
recent CMake and Python):
|
||||
|
||||
```bash
|
||||
python3 -m venv venv
|
||||
@ -313,6 +380,8 @@ if you really want to.
|
||||
|
||||
|
||||
[pre-commit]: https://pre-commit.com
|
||||
[clang-format]: https://clang.llvm.org/docs/ClangFormat.html
|
||||
[clang-tidy]: https://clang.llvm.org/extra/clang-tidy/
|
||||
[pybind11.readthedocs.org]: http://pybind11.readthedocs.org/en/latest
|
||||
[issue tracker]: https://github.com/pybind/pybind11/issues
|
||||
[gitter]: https://gitter.im/pybind/Lobby
|
||||
|
45
3rdparty/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
45
3rdparty/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
name: Bug Report
|
||||
description: File an issue about a bug
|
||||
title: "[BUG]: "
|
||||
labels: [triage]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Maintainers will only make a best effort to triage PRs. Please do your best to make the issue as easy to act on as possible, and only open if clearly a problem with pybind11 (ask first if unsure).
|
||||
- type: checkboxes
|
||||
id: steps
|
||||
attributes:
|
||||
label: Required prerequisites
|
||||
description: Make sure you've completed the following steps before submitting your issue -- thank you!
|
||||
options:
|
||||
- label: Make sure you've read the [documentation](https://pybind11.readthedocs.io). Your issue may be addressed there.
|
||||
required: true
|
||||
- label: Search the [issue tracker](https://github.com/pybind/pybind11/issues) and [Discussions](https:/pybind/pybind11/discussions) to verify that this hasn't already been reported. +1 or comment there if it has.
|
||||
required: true
|
||||
- label: Consider asking first in the [Gitter chat room](https://gitter.im/pybind/Lobby) or in a [Discussion](https:/pybind/pybind11/discussions/new).
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Problem description
|
||||
placeholder: >-
|
||||
Provide a short description, state the expected behavior and what
|
||||
actually happens. Include relevant information like what version of
|
||||
pybind11 you are using, what system you are on, and any useful commands
|
||||
/ output.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: code
|
||||
attributes:
|
||||
label: Reproducible example code
|
||||
placeholder: >-
|
||||
The code should be minimal, have no external dependencies, isolate the
|
||||
function(s) that cause breakage. Submit matched and complete C++ and
|
||||
Python snippets that can be easily compiled and run to diagnose the
|
||||
issue. If possible, make a PR with a new, failing test to give us a
|
||||
starting point to work on!
|
||||
render: text
|
@ -1,5 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Ask a question
|
||||
url: https://github.com/pybind/pybind11/discussions/new
|
||||
about: Please ask and answer questions here, or propose new ideas.
|
||||
- name: Gitter room
|
||||
url: https://gitter.im/pybind/Lobby
|
||||
about: A room for discussing pybind11 with an active community
|
||||
|
4
3rdparty/pybind11/.github/dependabot.yml
vendored
4
3rdparty/pybind11/.github/dependabot.yml
vendored
@ -5,7 +5,3 @@ updates:
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
ignore:
|
||||
# Offical actions have moving tags like v1
|
||||
# that are used, so they don't need updates here
|
||||
- dependency-name: "actions/*"
|
||||
|
@ -1,3 +1,7 @@
|
||||
<!--
|
||||
Title (above): please place [branch_name] at the beginning if you are targeting a branch other than master. *Do not target stable*.
|
||||
It is recommended to use conventional commit format, see conventionalcommits.org, but not required.
|
||||
-->
|
||||
## Description
|
||||
|
||||
<!-- Include relevant issues or PRs here, describe what changed and why -->
|
||||
@ -5,7 +9,8 @@
|
||||
|
||||
## Suggested changelog entry:
|
||||
|
||||
<!-- fill in the below block with the expected RestructuredText entry (delete if no entry needed) -->
|
||||
<!-- Fill in the below block with the expected RestructuredText entry. Delete if no entry needed;
|
||||
but do not delete header or rst block if an entry is needed! Will be collected via a script. -->
|
||||
|
||||
```rst
|
||||
|
||||
|
732
3rdparty/pybind11/.github/workflows/ci.yml
vendored
732
3rdparty/pybind11/.github/workflows/ci.yml
vendored
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@ jobs:
|
||||
matrix:
|
||||
runs-on: [ubuntu-latest, macos-latest, windows-latest]
|
||||
arch: [x64]
|
||||
cmake: [3.18]
|
||||
cmake: ["3.23"]
|
||||
|
||||
include:
|
||||
- runs-on: ubuntu-latest
|
||||
@ -29,22 +29,18 @@ jobs:
|
||||
arch: x64
|
||||
cmake: 3.7
|
||||
|
||||
- runs-on: windows-2016
|
||||
arch: x86
|
||||
cmake: 3.8
|
||||
|
||||
- runs-on: windows-2016
|
||||
arch: x86
|
||||
- runs-on: windows-2019
|
||||
arch: x64 # x86 compilers seem to be missing on 2019 image
|
||||
cmake: 3.18
|
||||
|
||||
name: 🐍 3.7 • CMake ${{ matrix.cmake }} • ${{ matrix.runs-on }}
|
||||
runs-on: ${{ matrix.runs-on }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Python 3.7
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.7
|
||||
architecture: ${{ matrix.arch }}
|
||||
@ -55,7 +51,7 @@ jobs:
|
||||
# An action for adding a specific version of CMake:
|
||||
# https://github.com/jwlawson/actions-setup-cmake
|
||||
- name: Setup CMake ${{ matrix.cmake }}
|
||||
uses: jwlawson/actions-setup-cmake@v1.3
|
||||
uses: jwlawson/actions-setup-cmake@v1.12
|
||||
with:
|
||||
cmake-version: ${{ matrix.cmake }}
|
||||
|
||||
|
23
3rdparty/pybind11/.github/workflows/format.yml
vendored
23
3rdparty/pybind11/.github/workflows/format.yml
vendored
@ -12,24 +12,33 @@ on:
|
||||
- stable
|
||||
- "v*"
|
||||
|
||||
env:
|
||||
FORCE_COLOR: 3
|
||||
|
||||
jobs:
|
||||
pre-commit:
|
||||
name: Format
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: pre-commit/action@v2.0.0
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
- name: Add matchers
|
||||
run: echo "::add-matcher::$GITHUB_WORKSPACE/.github/matchers/pylint.json"
|
||||
- uses: pre-commit/action@v3.0.0
|
||||
with:
|
||||
# Slow hooks are marked with manual - slow is okay here, run them too
|
||||
extra_args: --hook-stage manual --all-files
|
||||
|
||||
clang-tidy:
|
||||
# When making changes here, please also review the "Clang-Tidy" section
|
||||
# in .github/CONTRIBUTING.md and update as needed.
|
||||
name: Clang-Tidy
|
||||
runs-on: ubuntu-latest
|
||||
container: silkeh/clang:10
|
||||
container: silkeh/clang:13
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install requirements
|
||||
run: apt-get update && apt-get install -y python3-dev python3-pytest
|
||||
@ -37,10 +46,10 @@ jobs:
|
||||
- name: Configure
|
||||
run: >
|
||||
cmake -S . -B build
|
||||
-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--warnings-as-errors=*"
|
||||
-DCMAKE_CXX_CLANG_TIDY="$(which clang-tidy);--use-color;--warnings-as-errors=*"
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DDOWNLOAD_CATCH=ON
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build -j 2
|
||||
run: cmake --build build -j 2 -- --keep-going
|
||||
|
39
3rdparty/pybind11/.github/workflows/pip.yml
vendored
39
3rdparty/pybind11/.github/workflows/pip.yml
vendored
@ -12,24 +12,28 @@ on:
|
||||
types:
|
||||
- published
|
||||
|
||||
env:
|
||||
PIP_ONLY_BINARY: numpy
|
||||
|
||||
jobs:
|
||||
# This builds the sdists and wheels and makes sure the files are exactly as
|
||||
# expected. Using Windows and Python 2.7, since that is often the most
|
||||
# expected. Using Windows and Python 3.6, since that is often the most
|
||||
# challenging matrix element.
|
||||
test-packaging:
|
||||
name: 🐍 2.7 • 📦 tests • windows-latest
|
||||
name: 🐍 3.6 • 📦 tests • windows-latest
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup 🐍 2.7
|
||||
uses: actions/setup-python@v2
|
||||
- name: Setup 🐍 3.6
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 2.7
|
||||
python-version: 3.6
|
||||
|
||||
- name: Prepare env
|
||||
run: python -m pip install -r tests/requirements.txt --prefer-binary
|
||||
run: |
|
||||
python -m pip install -r tests/requirements.txt
|
||||
|
||||
- name: Python Packaging tests
|
||||
run: pytest tests/extra_python_package/
|
||||
@ -42,15 +46,16 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup 🐍 3.8
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
- name: Prepare env
|
||||
run: python -m pip install -r tests/requirements.txt build twine --prefer-binary
|
||||
run: |
|
||||
python -m pip install -r tests/requirements.txt build twine
|
||||
|
||||
- name: Python Packaging tests
|
||||
run: pytest tests/extra_python_package/
|
||||
@ -64,13 +69,13 @@ jobs:
|
||||
run: twine check dist/*
|
||||
|
||||
- name: Save standard package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: standard
|
||||
path: dist/pybind11-*
|
||||
|
||||
- name: Save global package
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: global
|
||||
path: dist/pybind11_global-*
|
||||
@ -85,19 +90,21 @@ jobs:
|
||||
needs: [packaging]
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v2
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.x"
|
||||
|
||||
# Downloads all to directories matching the artifact names
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
|
||||
- name: Publish standard package
|
||||
uses: pypa/gh-action-pypi-publish@v1.4.1
|
||||
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||
with:
|
||||
password: ${{ secrets.pypi_password }}
|
||||
packages_dir: standard/
|
||||
|
||||
- name: Publish global package
|
||||
uses: pypa/gh-action-pypi-publish@v1.4.1
|
||||
uses: pypa/gh-action-pypi-publish@v1.5.1
|
||||
with:
|
||||
password: ${{ secrets.pypi_password_global }}
|
||||
packages_dir: global/
|
||||
|
112
3rdparty/pybind11/.github/workflows/upstream.yml
vendored
Normal file
112
3rdparty/pybind11/.github/workflows/upstream.yml
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
|
||||
name: Upstream
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: upstream-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
PIP_ONLY_BINARY: numpy
|
||||
|
||||
jobs:
|
||||
standard:
|
||||
name: "🐍 3.11 latest internals • ubuntu-latest • x64"
|
||||
runs-on: ubuntu-latest
|
||||
if: "contains(github.event.pull_request.labels.*.name, 'python dev')"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Python 3.11
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: "3.11-dev"
|
||||
|
||||
- name: Setup Boost (Linux)
|
||||
if: runner.os == 'Linux'
|
||||
run: sudo apt-get install libboost-dev
|
||||
|
||||
- name: Update CMake
|
||||
uses: jwlawson/actions-setup-cmake@v1.12
|
||||
|
||||
- name: Prepare env
|
||||
run: |
|
||||
python -m pip install -r tests/requirements.txt
|
||||
|
||||
- name: Setup annotations on Linux
|
||||
if: runner.os == 'Linux'
|
||||
run: python -m pip install pytest-github-actions-annotate-failures
|
||||
|
||||
# First build - C++11 mode and inplace
|
||||
- name: Configure C++11
|
||||
run: >
|
||||
cmake -S . -B .
|
||||
-DPYBIND11_WERROR=ON
|
||||
-DDOWNLOAD_CATCH=ON
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DCMAKE_CXX_STANDARD=11
|
||||
|
||||
- name: Build C++11
|
||||
run: cmake --build . -j 2
|
||||
|
||||
- name: Python tests C++11
|
||||
run: cmake --build . --target pytest -j 2
|
||||
|
||||
- name: C++11 tests
|
||||
run: cmake --build . --target cpptest -j 2
|
||||
|
||||
- name: Interface test C++11
|
||||
run: cmake --build . --target test_cmake_build
|
||||
|
||||
- name: Clean directory
|
||||
run: git clean -fdx
|
||||
|
||||
# Second build - C++17 mode and in a build directory
|
||||
- name: Configure C++17
|
||||
run: >
|
||||
cmake -S . -B build2
|
||||
-DPYBIND11_WERROR=ON
|
||||
-DDOWNLOAD_CATCH=ON
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
${{ matrix.args }}
|
||||
${{ matrix.args2 }}
|
||||
|
||||
- name: Build
|
||||
run: cmake --build build2 -j 2
|
||||
|
||||
- name: Python tests
|
||||
run: cmake --build build2 --target pytest
|
||||
|
||||
- name: C++ tests
|
||||
run: cmake --build build2 --target cpptest
|
||||
|
||||
# Third build - C++17 mode with unstable ABI
|
||||
- name: Configure (unstable ABI)
|
||||
run: >
|
||||
cmake -S . -B build3
|
||||
-DPYBIND11_WERROR=ON
|
||||
-DDOWNLOAD_CATCH=ON
|
||||
-DDOWNLOAD_EIGEN=ON
|
||||
-DCMAKE_CXX_STANDARD=17
|
||||
-DPYBIND11_INTERNALS_VERSION=10000000
|
||||
"-DPYBIND11_TEST_OVERRIDE=test_call_policies.cpp;test_gil_scoped.cpp;test_thread.cpp"
|
||||
${{ matrix.args }}
|
||||
|
||||
- name: Build (unstable ABI)
|
||||
run: cmake --build build3 -j 2
|
||||
|
||||
- name: Python tests (unstable ABI)
|
||||
run: cmake --build build3 --target pytest
|
||||
|
||||
- name: Interface test
|
||||
run: cmake --build build3 --target test_cmake_build
|
||||
|
||||
# This makes sure the setup_helpers module can build packages using
|
||||
# setuptools
|
||||
- name: Setuptools helpers test
|
||||
run: pytest tests/extra_setuptools
|
2
3rdparty/pybind11/.gitignore
vendored
2
3rdparty/pybind11/.gitignore
vendored
@ -41,3 +41,5 @@ pybind11Targets.cmake
|
||||
/.vscode
|
||||
/pybind11/include/*
|
||||
/pybind11/share/*
|
||||
/docs/_build/*
|
||||
.ipynb_checkpoints/
|
||||
|
131
3rdparty/pybind11/.pre-commit-config.yaml
vendored
131
3rdparty/pybind11/.pre-commit-config.yaml
vendored
@ -12,49 +12,112 @@
|
||||
#
|
||||
# See https://github.com/pre-commit/pre-commit
|
||||
|
||||
# third-party content
|
||||
exclude: ^tools/JoinPaths.cmake$
|
||||
|
||||
repos:
|
||||
# Standard hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
rev: "v4.3.0"
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
- id: check-docstring-first
|
||||
- id: check-merge-conflict
|
||||
- id: check-symlinks
|
||||
- id: check-toml
|
||||
- id: check-yaml
|
||||
- id: debug-statements
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
- id: requirements-txt-fixer
|
||||
- id: trailing-whitespace
|
||||
- id: fix-encoding-pragma
|
||||
|
||||
# Upgrade old Python syntax
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: "v2.37.3"
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py36-plus]
|
||||
|
||||
# Nicely sort includes
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: "5.10.1"
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
# Black, the code formatter, natively supports pre-commit
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 20.8b1
|
||||
rev: "22.8.0" # Keep in sync with blacken-docs
|
||||
hooks:
|
||||
- id: black
|
||||
# By default, this ignores pyi files, though black supports them
|
||||
types: [text]
|
||||
files: \.pyi?$
|
||||
|
||||
# Also code format the docs
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: "v1.12.1"
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies:
|
||||
- black==22.8.0 # keep in sync with black hook
|
||||
|
||||
# Changes tabs to spaces
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.1.9
|
||||
rev: "v1.3.1"
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
|
||||
- repo: https://github.com/sirosen/texthooks
|
||||
rev: "0.4.0"
|
||||
hooks:
|
||||
- id: fix-ligatures
|
||||
- id: fix-smartquotes
|
||||
|
||||
# Autoremoves unused imports
|
||||
- repo: https://github.com/hadialqattan/pycln
|
||||
rev: "v2.1.1"
|
||||
hooks:
|
||||
- id: pycln
|
||||
stages: [manual]
|
||||
|
||||
# Checking for common mistakes
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: "v1.9.0"
|
||||
hooks:
|
||||
- id: python-check-blanket-noqa
|
||||
- id: python-check-blanket-type-ignore
|
||||
- id: python-no-log-warn
|
||||
- id: python-use-type-annotations
|
||||
- id: rst-backticks
|
||||
- id: rst-directive-colons
|
||||
- id: rst-inline-touching-normal
|
||||
|
||||
# Automatically remove noqa that are not used
|
||||
- repo: https://github.com/asottile/yesqa
|
||||
rev: "v1.4.0"
|
||||
hooks:
|
||||
- id: yesqa
|
||||
additional_dependencies: &flake8_dependencies
|
||||
- flake8-bugbear
|
||||
- pep8-naming
|
||||
|
||||
# Flake8 also supports pre-commit natively (same author)
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.8.3
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: "5.0.4"
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies: [flake8-bugbear, pep8-naming]
|
||||
exclude: ^(docs/.*|tools/.*)$
|
||||
additional_dependencies: *flake8_dependencies
|
||||
|
||||
# PyLint has native support - not always usable, but works for us
|
||||
- repo: https://github.com/PyCQA/pylint
|
||||
rev: "v2.15.2"
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^pybind11
|
||||
|
||||
# CMake formatting
|
||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||
rev: v0.6.13
|
||||
rev: "v0.6.13"
|
||||
hooks:
|
||||
- id: cmake-format
|
||||
additional_dependencies: [pyyaml]
|
||||
@ -63,38 +126,50 @@ repos:
|
||||
|
||||
# Check static types with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.790
|
||||
rev: "v0.971"
|
||||
hooks:
|
||||
- id: mypy
|
||||
# The default Python type ignores .pyi files, so let's rerun if detected
|
||||
types: [text]
|
||||
files: ^pybind11.*\.pyi?$
|
||||
# Running per-file misbehaves a bit, so just run on all files, it's fast
|
||||
pass_filenames: false
|
||||
args: []
|
||||
exclude: ^(tests|docs)/
|
||||
additional_dependencies: [nox, rich]
|
||||
|
||||
# Checks the manifest for missing files (native support)
|
||||
- repo: https://github.com/mgedmin/check-manifest
|
||||
rev: "0.43"
|
||||
rev: "0.48"
|
||||
hooks:
|
||||
- id: check-manifest
|
||||
# This is a slow hook, so only run this if --hook-stage manual is passed
|
||||
stages: [manual]
|
||||
additional_dependencies: [cmake, ninja]
|
||||
|
||||
# The original pybind11 checks for a few C++ style items
|
||||
# Check for spelling
|
||||
# Use tools/codespell_ignore_lines_from_errors.py
|
||||
# to rebuild .codespell-ignore-lines
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: "v2.2.1"
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ".supp$"
|
||||
args: ["-x", ".codespell-ignore-lines"]
|
||||
|
||||
# Check for common shell mistakes
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: "v0.8.0.4"
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
# Disallow some common capitalization mistakes
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: disallow-caps
|
||||
name: Disallow improper capitalization
|
||||
language: pygrep
|
||||
entry: PyBind|Numpy|Cmake|CCache
|
||||
exclude: .pre-commit-config.yaml
|
||||
entry: PyBind|Numpy|Cmake|CCache|PyTest
|
||||
exclude: ^\.pre-commit-config.yaml$
|
||||
|
||||
- repo: local
|
||||
# Clang format the codebase automatically
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: "v14.0.6"
|
||||
hooks:
|
||||
- id: check-style
|
||||
name: Classic check-style
|
||||
language: system
|
||||
types:
|
||||
- c++
|
||||
entry: ./tools/check-style.sh
|
||||
- id: clang-format
|
||||
types_or: [c++, c, cuda]
|
||||
|
76
3rdparty/pybind11/CMakeLists.txt
vendored
76
3rdparty/pybind11/CMakeLists.txt
vendored
@ -7,13 +7,18 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.4)
|
||||
|
||||
# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
|
||||
# The `cmake_minimum_required(VERSION 3.4...3.22)` 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.18)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.22)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.18)
|
||||
cmake_policy(VERSION 3.22)
|
||||
endif()
|
||||
|
||||
# Avoid infinite recursion if tests include this as a subdirectory
|
||||
if(DEFINED PYBIND11_MASTER_PROJECT)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Extract project version from source
|
||||
@ -73,6 +78,10 @@ if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
set(pybind11_system "")
|
||||
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
else()
|
||||
set(PYBIND11_MASTER_PROJECT OFF)
|
||||
set(pybind11_system SYSTEM)
|
||||
@ -82,6 +91,9 @@ endif()
|
||||
option(PYBIND11_INSTALL "Install pybind11 header files?" ${PYBIND11_MASTER_PROJECT})
|
||||
option(PYBIND11_TEST "Build pybind11 test suite?" ${PYBIND11_MASTER_PROJECT})
|
||||
option(PYBIND11_NOPYTHON "Disable search for Python" OFF)
|
||||
set(PYBIND11_INTERNALS_VERSION
|
||||
""
|
||||
CACHE STRING "Override the ABI version, may be used to enable the unstable ABI.")
|
||||
|
||||
cmake_dependent_option(
|
||||
USE_PYTHON_INCLUDE_DIR
|
||||
@ -98,6 +110,7 @@ set(PYBIND11_HEADERS
|
||||
include/pybind11/detail/descr.h
|
||||
include/pybind11/detail/init.h
|
||||
include/pybind11/detail/internals.h
|
||||
include/pybind11/detail/type_caster_base.h
|
||||
include/pybind11/detail/typeid.h
|
||||
include/pybind11/attr.h
|
||||
include/pybind11/buffer_info.h
|
||||
@ -109,6 +122,7 @@ set(PYBIND11_HEADERS
|
||||
include/pybind11/eigen.h
|
||||
include/pybind11/embed.h
|
||||
include/pybind11/eval.h
|
||||
include/pybind11/gil.h
|
||||
include/pybind11/iostream.h
|
||||
include/pybind11/functional.h
|
||||
include/pybind11/numpy.h
|
||||
@ -116,7 +130,8 @@ set(PYBIND11_HEADERS
|
||||
include/pybind11/pybind11.h
|
||||
include/pybind11/pytypes.h
|
||||
include/pybind11/stl.h
|
||||
include/pybind11/stl_bind.h)
|
||||
include/pybind11/stl_bind.h
|
||||
include/pybind11/stl/filesystem.h)
|
||||
|
||||
# Compare with grep and warn if mismatched
|
||||
if(PYBIND11_MASTER_PROJECT AND NOT CMAKE_VERSION VERSION_LESS 3.12)
|
||||
@ -159,14 +174,33 @@ endif()
|
||||
# You can also place ifs *in* the Config.in, but not here.
|
||||
|
||||
# This section builds targets, but does *not* touch Python
|
||||
# Non-IMPORT targets cannot be defined twice
|
||||
if(NOT TARGET pybind11_headers)
|
||||
# Build the headers-only target (no Python included):
|
||||
# (long name used here to keep this from clashing in subdirectory mode)
|
||||
add_library(pybind11_headers INTERFACE)
|
||||
add_library(pybind11::pybind11_headers ALIAS pybind11_headers) # to match exported target
|
||||
add_library(pybind11::headers ALIAS pybind11_headers) # easier to use/remember
|
||||
|
||||
# Build the headers-only target (no Python included):
|
||||
# (long name used here to keep this from clashing in subdirectory mode)
|
||||
add_library(pybind11_headers INTERFACE)
|
||||
add_library(pybind11::pybind11_headers ALIAS pybind11_headers) # to match exported target
|
||||
add_library(pybind11::headers ALIAS pybind11_headers) # easier to use/remember
|
||||
target_include_directories(
|
||||
pybind11_headers ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${pybind11_INCLUDE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals
|
||||
cxx_right_angle_brackets)
|
||||
if(NOT "${PYBIND11_INTERNALS_VERSION}" STREQUAL "")
|
||||
target_compile_definitions(
|
||||
pybind11_headers INTERFACE "PYBIND11_INTERNALS_VERSION=${PYBIND11_INTERNALS_VERSION}")
|
||||
endif()
|
||||
else()
|
||||
# It is invalid to install a target twice, too.
|
||||
set(PYBIND11_INSTALL OFF)
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11Common.cmake")
|
||||
# https://github.com/jtojnar/cmake-snips/#concatenating-paths-when-building-pkg-config-files
|
||||
# TODO: cmake 3.20 adds the cmake_path() function, which obsoletes this snippet
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/tools/JoinPaths.cmake")
|
||||
|
||||
# Relative directory setting
|
||||
if(USE_PYTHON_INCLUDE_DIR AND DEFINED Python_INCLUDE_DIRS)
|
||||
@ -175,20 +209,18 @@ elseif(USE_PYTHON_INCLUDE_DIR AND DEFINED PYTHON_INCLUDE_DIR)
|
||||
file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX} ${PYTHON_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Fill in headers target
|
||||
target_include_directories(
|
||||
pybind11_headers ${pybind11_system} INTERFACE $<BUILD_INTERFACE:${pybind11_INCLUDE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
target_compile_features(pybind11_headers INTERFACE cxx_inheriting_constructors cxx_user_literals
|
||||
cxx_right_angle_brackets)
|
||||
|
||||
if(PYBIND11_INSTALL)
|
||||
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
set(PYBIND11_CMAKECONFIG_INSTALL_DIR
|
||||
"${CMAKE_INSTALL_DATAROOTDIR}/cmake/${PROJECT_NAME}"
|
||||
CACHE STRING "install path for pybind11Config.cmake")
|
||||
|
||||
if(IS_ABSOLUTE "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
set(pybind11_INCLUDEDIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
|
||||
else()
|
||||
set(pybind11_INCLUDEDIR "\$\{PACKAGE_PREFIX_DIR\}/${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
endif()
|
||||
|
||||
configure_package_config_file(
|
||||
tools/${PROJECT_NAME}Config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake"
|
||||
INSTALL_DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
|
||||
@ -233,6 +265,16 @@ if(PYBIND11_INSTALL)
|
||||
NAMESPACE "pybind11::"
|
||||
DESTINATION ${PYBIND11_CMAKECONFIG_INSTALL_DIR})
|
||||
|
||||
# pkg-config support
|
||||
if(NOT prefix_for_pc_file)
|
||||
set(prefix_for_pc_file "${CMAKE_INSTALL_PREFIX}")
|
||||
endif()
|
||||
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/pybind11.pc.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc" @ONLY)
|
||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pybind11.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig/")
|
||||
|
||||
# Uninstall target
|
||||
if(PYBIND11_MASTER_PROJECT)
|
||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/tools/cmake_uninstall.cmake.in"
|
||||
|
1
3rdparty/pybind11/MANIFEST.in
vendored
1
3rdparty/pybind11/MANIFEST.in
vendored
@ -1,6 +1,5 @@
|
||||
recursive-include pybind11/include/pybind11 *.h
|
||||
recursive-include pybind11 *.py
|
||||
recursive-include pybind11 py.typed
|
||||
recursive-include pybind11 *.pyi
|
||||
include pybind11/share/cmake/pybind11/*.cmake
|
||||
include LICENSE README.rst pyproject.toml setup.py setup.cfg
|
||||
|
63
3rdparty/pybind11/README.rst
vendored
63
3rdparty/pybind11/README.rst
vendored
@ -3,20 +3,16 @@
|
||||
|
||||
**pybind11 — Seamless operability between C++11 and Python**
|
||||
|
||||
|Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |CI| |Build status|
|
||||
|Latest Documentation Status| |Stable Documentation Status| |Gitter chat| |GitHub Discussions| |CI| |Build status|
|
||||
|
||||
.. warning::
|
||||
|Repology| |PyPI package| |Conda-forge| |Python Versions|
|
||||
|
||||
Combining older versions of pybind11 (< 2.6.0) with the brand-new Python
|
||||
3.9.0 will trigger undefined behavior that typically manifests as crashes
|
||||
during interpreter shutdown (but could also destroy your data. **You have been
|
||||
warned.**)
|
||||
`Setuptools example <https://github.com/pybind/python_example>`_
|
||||
• `Scikit-build example <https://github.com/pybind/scikit_build_example>`_
|
||||
• `CMake example <https://github.com/pybind/cmake_example>`_
|
||||
|
||||
.. start
|
||||
|
||||
We recommend that you wait for Python 3.9.1 slated for release in December,
|
||||
which will include a `fix <https://github.com/python/cpython/pull/22670>`_
|
||||
that resolves this problem. In the meantime, please update to the latest
|
||||
version of pybind11 (2.6.0 or newer), which includes a temporary workaround
|
||||
specifically when Python 3.9.0 is detected at runtime.
|
||||
|
||||
**pybind11** is a lightweight header-only library that exposes C++ types
|
||||
in Python and vice versa, mainly to create Python bindings of existing
|
||||
@ -36,9 +32,9 @@ this heavy machinery has become an excessively large and unnecessary
|
||||
dependency.
|
||||
|
||||
Think of this library as a tiny self-contained version of Boost.Python
|
||||
with everything stripped away that isn’t relevant for binding
|
||||
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 (2.7 or 3.5+, or PyPy) and the C++
|
||||
lines of code and depend on Python (3.6+, or PyPy) and the C++
|
||||
standard library. This compact implementation was possible thanks to
|
||||
some of the new C++11 language features (specifically: tuples, lambda
|
||||
functions and variadic templates). Since its creation, this library has
|
||||
@ -82,8 +78,8 @@ Goodies
|
||||
In addition to the core functionality, pybind11 provides some extra
|
||||
goodies:
|
||||
|
||||
- Python 2.7, 3.5+, and PyPy/PyPy3 7.3 are supported with an
|
||||
implementation-agnostic interface.
|
||||
- Python 3.6+, 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
|
||||
variables. The lambda capture data is stored inside the resulting
|
||||
@ -92,8 +88,8 @@ goodies:
|
||||
- pybind11 uses C++11 move constructors and move assignment operators
|
||||
whenever possible to efficiently transfer custom data types.
|
||||
|
||||
- It’s easy to expose the internal storage of custom data types through
|
||||
Pythons’ buffer protocols. This is handy e.g. for fast conversion
|
||||
- It's easy to expose the internal storage of custom data types through
|
||||
Pythons' buffer protocols. This is handy e.g. for fast conversion
|
||||
between C++ matrix classes like Eigen and NumPy without expensive
|
||||
copy operations.
|
||||
|
||||
@ -101,7 +97,7 @@ goodies:
|
||||
transparently applied to all entries of one or more NumPy array
|
||||
arguments.
|
||||
|
||||
- Python’s slice-based access and assignment operations can be
|
||||
- Python's slice-based access and assignment operations can be
|
||||
supported with just a few lines of code.
|
||||
|
||||
- Everything is contained in just a few header files; there is no need
|
||||
@ -110,7 +106,7 @@ goodies:
|
||||
- Binaries are generally smaller by a factor of at least 2 compared to
|
||||
equivalent bindings generated by Boost.Python. A recent pybind11
|
||||
conversion of PyRosetta, an enormous Boost.Python binding project,
|
||||
`reported <http://graylab.jhu.edu/RosettaCon2016/PyRosetta-4.pdf>`_
|
||||
`reported <https://graylab.jhu.edu/Sergey/2016.RosettaCon/PyRosetta-4.pdf>`_
|
||||
a binary size reduction of **5.4x** and compile time reduction by
|
||||
**5.8x**.
|
||||
|
||||
@ -123,15 +119,14 @@ goodies:
|
||||
Supported compilers
|
||||
-------------------
|
||||
|
||||
1. Clang/LLVM 3.3 or newer (for Apple Xcode’s clang, this is 5.0.0 or
|
||||
1. Clang/LLVM 3.3 or newer (for Apple Xcode's clang, this is 5.0.0 or
|
||||
newer)
|
||||
2. GCC 4.8 or newer
|
||||
3. Microsoft Visual Studio 2015 Update 3 or newer
|
||||
4. Intel C++ compiler 18 or newer
|
||||
(`possible issue <https://github.com/pybind/pybind11/pull/2573>`_ on 20.2)
|
||||
5. Cygwin/GCC (tested on 2.5.1)
|
||||
6. NVCC (CUDA 11.0 tested)
|
||||
7. NVIDIA PGI (20.7 and 20.9 tested)
|
||||
3. Microsoft Visual Studio 2017 or newer
|
||||
4. Intel classic C++ compiler 18 or newer (ICC 20.2 tested in CI)
|
||||
5. Cygwin/GCC (previously tested on 2.5.1)
|
||||
6. NVCC (CUDA 11.0 tested in CI)
|
||||
7. NVIDIA PGI (20.9 tested in CI)
|
||||
|
||||
About
|
||||
-----
|
||||
@ -139,9 +134,9 @@ About
|
||||
This project was created by `Wenzel
|
||||
Jakob <http://rgl.epfl.ch/people/wjakob>`_. Significant features and/or
|
||||
improvements to the code were contributed by Jonas Adler, Lori A. Burns,
|
||||
Sylvain Corlay, Eric Cousineau, Ralf Grosse-Kunstleve, Trent Houliston, Axel
|
||||
Sylvain Corlay, Eric Cousineau, Aaron Gokaslan, Ralf Grosse-Kunstleve, Trent Houliston, Axel
|
||||
Huebl, @hulucc, Yannick Jadoul, Sergey Lyskov Johan Mabille, Tomasz Miąsko,
|
||||
Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim
|
||||
Dean Moldovan, Ben Pritchard, Jason Rhinelander, Boris Schäling, Pim
|
||||
Schellart, Henry Schreiner, Ivan Smirnov, Boris Staletic, and Patrick Stewart.
|
||||
|
||||
We thank Google for a generous financial contribution to the continuous
|
||||
@ -165,7 +160,7 @@ to the terms and conditions of this license.
|
||||
|
||||
.. |Latest Documentation Status| image:: https://readthedocs.org/projects/pybind11/badge?version=latest
|
||||
:target: http://pybind11.readthedocs.org/en/latest
|
||||
.. |Stable Documentation Status| image:: https://img.shields.io/badge/docs-stable-blue
|
||||
.. |Stable Documentation Status| image:: https://img.shields.io/badge/docs-stable-blue.svg
|
||||
:target: http://pybind11.readthedocs.org/en/stable
|
||||
.. |Gitter chat| image:: https://img.shields.io/gitter/room/gitterHQ/gitter.svg
|
||||
:target: https://gitter.im/pybind/Lobby
|
||||
@ -173,3 +168,13 @@ to the terms and conditions of this license.
|
||||
:target: https://github.com/pybind/pybind11/actions
|
||||
.. |Build status| image:: https://ci.appveyor.com/api/projects/status/riaj54pn4h08xy40?svg=true
|
||||
:target: https://ci.appveyor.com/project/wjakob/pybind11
|
||||
.. |PyPI package| image:: https://img.shields.io/pypi/v/pybind11.svg
|
||||
:target: https://pypi.org/project/pybind11/
|
||||
.. |Conda-forge| image:: https://img.shields.io/conda/vn/conda-forge/pybind11.svg
|
||||
:target: https://github.com/conda-forge/pybind11-feedstock
|
||||
.. |Repology| image:: https://repology.org/badge/latest-versions/python:pybind11.svg
|
||||
:target: https://repology.org/project/python:pybind11/versions
|
||||
.. |Python Versions| image:: https://img.shields.io/pypi/pyversions/pybind11.svg
|
||||
:target: https://pypi.org/project/pybind11/
|
||||
.. |GitHub Discussions| image:: https://img.shields.io/static/v1?label=Discussions&message=Ask&color=blue&logo=github
|
||||
:target: https://github.com/pybind/pybind11/discussions
|
||||
|
4
3rdparty/pybind11/docs/Doxyfile
vendored
4
3rdparty/pybind11/docs/Doxyfile
vendored
@ -18,6 +18,4 @@ ALIASES += "endrst=\endverbatim"
|
||||
QUIET = YES
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = NO
|
||||
PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS \
|
||||
PY_MAJOR_VERSION=3 \
|
||||
PYBIND11_NOINLINE
|
||||
PREDEFINED = PYBIND11_NOINLINE
|
||||
|
3
3rdparty/pybind11/docs/_static/css/custom.css
vendored
Normal file
3
3rdparty/pybind11/docs/_static/css/custom.css
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.highlight .go {
|
||||
color: #707070;
|
||||
}
|
@ -26,7 +26,9 @@ The following Python snippet demonstrates the intended usage from the Python sid
|
||||
def __int__(self):
|
||||
return 123
|
||||
|
||||
|
||||
from example import print
|
||||
|
||||
print(A())
|
||||
|
||||
To register the necessary conversion routines, it is necessary to add an
|
||||
@ -36,7 +38,7 @@ type is explicitly allowed.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
namespace pybind11 { namespace detail {
|
||||
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||
template <> struct type_caster<inty> {
|
||||
public:
|
||||
/**
|
||||
@ -44,7 +46,7 @@ type is explicitly allowed.
|
||||
* function signatures and declares a local variable
|
||||
* 'value' of type inty
|
||||
*/
|
||||
PYBIND11_TYPE_CASTER(inty, _("inty"));
|
||||
PYBIND11_TYPE_CASTER(inty, const_name("inty"));
|
||||
|
||||
/**
|
||||
* Conversion part 1 (Python->C++): convert a PyObject into a inty
|
||||
@ -76,7 +78,7 @@ type is explicitly allowed.
|
||||
return PyLong_FromLong(src.long_value);
|
||||
}
|
||||
};
|
||||
}} // namespace pybind11::detail
|
||||
}} // namespace PYBIND11_NAMESPACE::detail
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -52,7 +52,7 @@ can be mapped *and* if the numpy array is writeable (that is
|
||||
the passed variable will be transparently carried out directly on the
|
||||
``numpy.ndarray``.
|
||||
|
||||
This means you can can write code such as the following and have it work as
|
||||
This means you can write code such as the following and have it work as
|
||||
expected:
|
||||
|
||||
.. code-block:: cpp
|
||||
@ -112,7 +112,7 @@ example:
|
||||
.. code-block:: python
|
||||
|
||||
a = MyClass()
|
||||
m = a.get_matrix() # flags.writeable = True, flags.owndata = False
|
||||
m = a.get_matrix() # flags.writeable = True, flags.owndata = False
|
||||
v = a.view_matrix() # flags.writeable = False, flags.owndata = False
|
||||
c = a.copy_matrix() # flags.writeable = True, flags.owndata = True
|
||||
# m[5,6] and v[5,6] refer to the same element, c[5,6] does not.
|
||||
@ -203,7 +203,7 @@ adding the ``order='F'`` option when creating an array:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
myarray = np.array(source, order='F')
|
||||
myarray = np.array(source, order="F")
|
||||
|
||||
Such an object will be passable to a bound function accepting an
|
||||
``Eigen::Ref<MatrixXd>`` (or similar column-major Eigen type).
|
||||
|
181
3rdparty/pybind11/docs/advanced/cast/overview.rst
vendored
181
3rdparty/pybind11/docs/advanced/cast/overview.rst
vendored
@ -75,91 +75,96 @@ The following basic data types are supported out of the box (some may require
|
||||
an additional extension header to be included). To pass other data structures
|
||||
as arguments and return values, refer to the section on binding :ref:`classes`.
|
||||
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| Data type | Description | Header file |
|
||||
+====================================+===========================+===============================+
|
||||
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``char16_t`` | UTF-16 character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``char32_t`` | UTF-32 character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``const char16_t *`` | UTF-16 string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``const char32_t *`` | UTF-32 string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::u16string`` | STL dynamic UTF-16 string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::u32string`` | STL dynamic UTF-32 string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` |
|
||||
| ``std::u16string_view``, etc. | | |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::deque<T>`` | STL double-ended queue | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::valarray<T>`` | STL value array | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::optional<T>`` | STL optional type (C++17) | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::variant<...>`` | Type-safe union (C++17) | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``std::chrono::time_point<...>`` | STL date/time | :file:`pybind11/chrono.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-------------------------------+
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| Data type | Description | Header file |
|
||||
+====================================+===========================+===================================+
|
||||
| ``int8_t``, ``uint8_t`` | 8-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``int16_t``, ``uint16_t`` | 16-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``int32_t``, ``uint32_t`` | 32-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``int64_t``, ``uint64_t`` | 64-bit integers | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``ssize_t``, ``size_t`` | Platform-dependent size | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``float``, ``double`` | Floating point types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``bool`` | Two-state Boolean type | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``char`` | Character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``char16_t`` | UTF-16 character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``char32_t`` | UTF-32 character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``wchar_t`` | Wide character literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``const char *`` | UTF-8 string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``const char16_t *`` | UTF-16 string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``const char32_t *`` | UTF-32 string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``const wchar_t *`` | Wide string literal | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::string`` | STL dynamic UTF-8 string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::u16string`` | STL dynamic UTF-16 string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::u32string`` | STL dynamic UTF-32 string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::wstring`` | STL dynamic wide string | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::string_view``, | STL C++17 string views | :file:`pybind11/pybind11.h` |
|
||||
| ``std::u16string_view``, etc. | | |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::pair<T1, T2>`` | Pair of two custom types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::tuple<...>`` | Arbitrary tuple of types | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::reference_wrapper<...>`` | Reference type wrapper | :file:`pybind11/pybind11.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::complex<T>`` | Complex numbers | :file:`pybind11/complex.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::array<T, Size>`` | STL static array | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::vector<T>`` | STL dynamic array | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::deque<T>`` | STL double-ended queue | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::valarray<T>`` | STL value array | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::list<T>`` | STL linked list | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::map<T1, T2>`` | STL ordered map | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::unordered_map<T1, T2>`` | STL unordered map | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::set<T>`` | STL ordered set | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::unordered_set<T>`` | STL unordered set | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::optional<T>`` | STL optional type (C++17) | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::experimental::optional<T>`` | STL optional type (exp.) | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::variant<...>`` | Type-safe union (C++17) | :file:`pybind11/stl.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::filesystem::path<T>`` | STL path (C++17) [#]_ | :file:`pybind11/stl/filesystem.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::function<...>`` | STL polymorphic function | :file:`pybind11/functional.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::chrono::duration<...>`` | STL time duration | :file:`pybind11/chrono.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``std::chrono::time_point<...>`` | STL date/time | :file:`pybind11/chrono.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``Eigen::Matrix<...>`` | Eigen: dense matrix | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``Eigen::Map<...>`` | Eigen: mapped memory | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
| ``Eigen::SparseMatrix<...>`` | Eigen: sparse matrix | :file:`pybind11/eigen.h` |
|
||||
+------------------------------------+---------------------------+-----------------------------------+
|
||||
|
||||
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
||||
``os.PathLike`` is converted to ``std::filesystem::path``.
|
||||
|
19
3rdparty/pybind11/docs/advanced/cast/stl.rst
vendored
19
3rdparty/pybind11/docs/advanced/cast/stl.rst
vendored
@ -42,7 +42,7 @@ types:
|
||||
.. code-block:: cpp
|
||||
|
||||
// `boost::optional` as an example -- can be any `std::optional`-like container
|
||||
namespace pybind11 { namespace detail {
|
||||
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||
template <typename T>
|
||||
struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};
|
||||
}}
|
||||
@ -54,7 +54,7 @@ for custom variant types:
|
||||
.. code-block:: cpp
|
||||
|
||||
// `boost::variant` as an example -- can be any `std::variant`-like container
|
||||
namespace pybind11 { namespace detail {
|
||||
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||
template <typename... Ts>
|
||||
struct type_caster<boost::variant<Ts...>> : variant_caster<boost::variant<Ts...>> {};
|
||||
|
||||
@ -66,18 +66,27 @@ for custom variant types:
|
||||
return boost::apply_visitor(args...);
|
||||
}
|
||||
};
|
||||
}} // namespace pybind11::detail
|
||||
}} // namespace PYBIND11_NAMESPACE::detail
|
||||
|
||||
The ``visit_helper`` specialization is not required if your ``name::variant`` provides
|
||||
a ``name::visit()`` function. For any other function name, the specialization must be
|
||||
included to tell pybind11 how to visit the variant.
|
||||
|
||||
.. warning::
|
||||
|
||||
When converting a ``variant`` type, pybind11 follows the same rules as when
|
||||
determining which function overload to call (:ref:`overload_resolution`), and
|
||||
so the same caveats hold. In particular, the order in which the ``variant``'s
|
||||
alternatives are listed is important, since pybind11 will try conversions in
|
||||
this order. This means that, for example, when converting ``variant<int, bool>``,
|
||||
the ``bool`` variant will never be selected, as any Python ``bool`` is already
|
||||
an ``int`` and is convertible to a C++ ``int``. Changing the order of alternatives
|
||||
(and using ``variant<bool, int>``, in this example) provides a solution.
|
||||
|
||||
.. note::
|
||||
|
||||
pybind11 only supports the modern implementation of ``boost::variant``
|
||||
which makes use of variadic templates. This requires Boost 1.56 or newer.
|
||||
Additionally, on Windows, MSVC 2017 is required because ``boost::variant``
|
||||
falls back to the old non-variadic implementation on MSVC 2015.
|
||||
|
||||
.. _opaque:
|
||||
|
||||
|
51
3rdparty/pybind11/docs/advanced/cast/strings.rst
vendored
51
3rdparty/pybind11/docs/advanced/cast/strings.rst
vendored
@ -1,14 +1,6 @@
|
||||
Strings, bytes and Unicode conversions
|
||||
######################################
|
||||
|
||||
.. note::
|
||||
|
||||
This section discusses string handling in terms of Python 3 strings. For
|
||||
Python 2.7, replace all occurrences of ``str`` with ``unicode`` and
|
||||
``bytes`` with ``str``. Python 2.7 users may find it best to use ``from
|
||||
__future__ import unicode_literals`` to avoid unintentionally using ``str``
|
||||
instead of ``unicode``.
|
||||
|
||||
Passing Python strings to C++
|
||||
=============================
|
||||
|
||||
@ -36,13 +28,13 @@ everywhere <http://utf8everywhere.org/>`_.
|
||||
}
|
||||
);
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> utf8_test('🎂')
|
||||
>>> utf8_test("🎂")
|
||||
utf-8 is icing on the cake.
|
||||
🎂
|
||||
|
||||
>>> utf8_charptr('🍕')
|
||||
>>> utf8_charptr("🍕")
|
||||
My favorite food is
|
||||
🍕
|
||||
|
||||
@ -58,9 +50,9 @@ Passing bytes to C++
|
||||
--------------------
|
||||
|
||||
A Python ``bytes`` object will be passed to C++ functions that accept
|
||||
``std::string`` or ``char*`` *without* conversion. On Python 3, in order to
|
||||
make a function *only* accept ``bytes`` (and not ``str``), declare it as taking
|
||||
a ``py::bytes`` argument.
|
||||
``std::string`` or ``char*`` *without* conversion. In order to make a function
|
||||
*only* accept ``bytes`` (and not ``str``), declare it as taking a ``py::bytes``
|
||||
argument.
|
||||
|
||||
|
||||
Returning C++ strings to Python
|
||||
@ -80,7 +72,7 @@ raise a ``UnicodeDecodeError``.
|
||||
}
|
||||
);
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> isinstance(example.std_string_return(), str)
|
||||
True
|
||||
@ -114,7 +106,7 @@ conversion has the same overhead as implicit conversion.
|
||||
}
|
||||
);
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> str_output()
|
||||
'Send your résumé to Alice in HR'
|
||||
@ -143,7 +135,7 @@ returned to Python as ``bytes``, then one can return the data as a
|
||||
}
|
||||
);
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> example.return_bytes()
|
||||
b'\xba\xd0\xba\xd0'
|
||||
@ -160,7 +152,7 @@ encoding, but cannot convert ``std::string`` back to ``bytes`` implicitly.
|
||||
}
|
||||
);
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> isinstance(example.asymmetry(b"have some bytes"), str)
|
||||
True
|
||||
@ -204,11 +196,6 @@ decoded to Python ``str``.
|
||||
}
|
||||
);
|
||||
|
||||
.. warning::
|
||||
|
||||
Wide character strings may not work as described on Python 2.7 or Python
|
||||
3.3 compiled with ``--enable-unicode=ucs2``.
|
||||
|
||||
Strings in multibyte encodings such as Shift-JIS must transcoded to a
|
||||
UTF-8/16/32 before being returned to Python.
|
||||
|
||||
@ -229,16 +216,16 @@ character.
|
||||
m.def("pass_char", [](char c) { return c; });
|
||||
m.def("pass_wchar", [](wchar_t w) { return w; });
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> example.pass_char('A')
|
||||
>>> example.pass_char("A")
|
||||
'A'
|
||||
|
||||
While C++ will cast integers to character types (``char c = 0x65;``), pybind11
|
||||
does not convert Python integers to characters implicitly. The Python function
|
||||
``chr()`` can be used to convert integers to characters.
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> example.pass_char(0x65)
|
||||
TypeError
|
||||
@ -259,17 +246,17 @@ a combining acute accent). The combining character will be lost if the
|
||||
two-character sequence is passed as an argument, even though it renders as a
|
||||
single grapheme.
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> example.pass_wchar('é')
|
||||
>>> example.pass_wchar("é")
|
||||
'é'
|
||||
|
||||
>>> combining_e_acute = 'e' + '\u0301'
|
||||
>>> combining_e_acute = "e" + "\u0301"
|
||||
|
||||
>>> combining_e_acute
|
||||
'é'
|
||||
|
||||
>>> combining_e_acute == 'é'
|
||||
>>> combining_e_acute == "é"
|
||||
False
|
||||
|
||||
>>> example.pass_wchar(combining_e_acute)
|
||||
@ -278,9 +265,9 @@ single grapheme.
|
||||
Normalizing combining characters before passing the character literal to C++
|
||||
may resolve *some* of these issues:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> example.pass_wchar(unicodedata.normalize('NFC', combining_e_acute))
|
||||
>>> example.pass_wchar(unicodedata.normalize("NFC", combining_e_acute))
|
||||
'é'
|
||||
|
||||
In some languages (Thai for example), there are `graphemes that cannot be
|
||||
|
144
3rdparty/pybind11/docs/advanced/classes.rst
vendored
144
3rdparty/pybind11/docs/advanced/classes.rst
vendored
@ -9,7 +9,7 @@ that you are already familiar with the basics from :doc:`/classes`.
|
||||
Overriding virtual functions in Python
|
||||
======================================
|
||||
|
||||
Suppose that a C++ class or interface has a virtual function that we'd like to
|
||||
Suppose that a C++ class or interface has a virtual function that we'd like
|
||||
to override from within Python (we'll focus on the class ``Animal``; ``Dog`` is
|
||||
given as a specific example of how one would do this with traditional C++
|
||||
code).
|
||||
@ -133,14 +133,14 @@ a virtual method call.
|
||||
>>> from example import *
|
||||
>>> d = Dog()
|
||||
>>> call_go(d)
|
||||
u'woof! woof! woof! '
|
||||
'woof! woof! woof! '
|
||||
>>> class Cat(Animal):
|
||||
... def go(self, n_times):
|
||||
... return "meow! " * n_times
|
||||
... return "meow! " * n_times
|
||||
...
|
||||
>>> c = Cat()
|
||||
>>> call_go(c)
|
||||
u'meow! meow! meow! '
|
||||
'meow! meow! meow! '
|
||||
|
||||
If you are defining a custom constructor in a derived Python class, you *must*
|
||||
ensure that you explicitly call the bound C++ constructor using ``__init__``,
|
||||
@ -159,8 +159,9 @@ Here is an example:
|
||||
|
||||
class Dachshund(Dog):
|
||||
def __init__(self, name):
|
||||
Dog.__init__(self) # Without this, a TypeError is raised.
|
||||
Dog.__init__(self) # Without this, a TypeError is raised.
|
||||
self.name = name
|
||||
|
||||
def bark(self):
|
||||
return "yap!"
|
||||
|
||||
@ -259,7 +260,7 @@ override the ``name()`` method):
|
||||
|
||||
.. note::
|
||||
|
||||
Note the trailing commas in the ``PYBIND11_OVERIDE`` calls to ``name()``
|
||||
Note the trailing commas in the ``PYBIND11_OVERRIDE`` calls to ``name()``
|
||||
and ``bark()``. These are needed to portably implement a trampoline for a
|
||||
function that does not take any arguments. For functions that take
|
||||
a nonzero number of arguments, the trailing comma must be omitted.
|
||||
@ -804,7 +805,7 @@ to bind these two functions:
|
||||
}
|
||||
));
|
||||
|
||||
The ``__setstate__`` part of the ``py::picke()`` definition follows the same
|
||||
The ``__setstate__`` part of the ``py::pickle()`` definition follows the same
|
||||
rules as the single-argument version of ``py::init()``. The return type can be
|
||||
a value, pointer or holder type. See :ref:`custom_constructors` for details.
|
||||
|
||||
@ -812,26 +813,21 @@ An instance can now be pickled as follows:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
import cPickle as pickle # Use cPickle on Python 2.7
|
||||
except ImportError:
|
||||
import pickle
|
||||
import pickle
|
||||
|
||||
p = Pickleable("test_value")
|
||||
p.setExtra(15)
|
||||
data = pickle.dumps(p, 2)
|
||||
data = pickle.dumps(p)
|
||||
|
||||
|
||||
.. note::
|
||||
Note that only the cPickle module is supported on Python 2.7.
|
||||
|
||||
The second argument to ``dumps`` is also crucial: it selects the pickle
|
||||
protocol version 2, since the older version 1 is not supported. Newer
|
||||
versions are also fine—for instance, specify ``-1`` to always use the
|
||||
latest available version. Beware: failure to follow these instructions
|
||||
will cause important pybind11 memory allocation routines to be skipped
|
||||
during unpickling, which will likely lead to memory corruption and/or
|
||||
segmentation faults.
|
||||
If given, the second argument to ``dumps`` must be 2 or larger - 0 and 1 are
|
||||
not supported. Newer versions are also fine; for instance, specify ``-1`` to
|
||||
always use the latest available version. Beware: failure to follow these
|
||||
instructions will cause important pybind11 memory allocation routines to be
|
||||
skipped during unpickling, which will likely lead to memory corruption
|
||||
and/or segmentation faults. Python defaults to version 3 (Python 3-3.7) and
|
||||
version 4 for Python 3.8+.
|
||||
|
||||
.. seealso::
|
||||
|
||||
@ -848,11 +844,9 @@ Python normally uses references in assignments. Sometimes a real copy is needed
|
||||
to prevent changing all copies. The ``copy`` module [#f5]_ provides these
|
||||
capabilities.
|
||||
|
||||
On Python 3, a class with pickle support is automatically also (deep)copy
|
||||
A class with pickle support is automatically also (deep)copy
|
||||
compatible. However, performance can be improved by adding custom
|
||||
``__copy__`` and ``__deepcopy__`` methods. With Python 2.7, these custom methods
|
||||
are mandatory for (deep)copy compatibility, because pybind11 only supports
|
||||
cPickle.
|
||||
``__copy__`` and ``__deepcopy__`` methods.
|
||||
|
||||
For simple classes (deep)copy can be enabled by using the copy constructor,
|
||||
which should look as follows:
|
||||
@ -1124,13 +1118,6 @@ described trampoline:
|
||||
py::class_<A, Trampoline>(m, "A") // <-- `Trampoline` here
|
||||
.def("foo", &Publicist::foo); // <-- `Publicist` here, not `Trampoline`!
|
||||
|
||||
.. note::
|
||||
|
||||
MSVC 2015 has a compiler bug (fixed in version 2017) which
|
||||
requires a more explicit function binding in the form of
|
||||
``.def("foo", static_cast<int (A::*)() const>(&Publicist::foo));``
|
||||
where ``int (A::*)() const`` is the type of ``A::foo``.
|
||||
|
||||
Binding final classes
|
||||
=====================
|
||||
|
||||
@ -1153,12 +1140,65 @@ error:
|
||||
|
||||
>>> class PyFinalChild(IsFinal):
|
||||
... pass
|
||||
...
|
||||
TypeError: type 'IsFinal' is not an acceptable base type
|
||||
|
||||
.. note:: This attribute is currently ignored on PyPy
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
Binding classes with template parameters
|
||||
========================================
|
||||
|
||||
pybind11 can also wrap classes that have template parameters. Consider these classes:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
struct Cat {};
|
||||
struct Dog {};
|
||||
|
||||
template <typename PetType>
|
||||
struct Cage {
|
||||
Cage(PetType& pet);
|
||||
PetType& get();
|
||||
};
|
||||
|
||||
C++ templates may only be instantiated at compile time, so pybind11 can only
|
||||
wrap instantiated templated classes. You cannot wrap a non-instantiated template:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// BROKEN (this will not compile)
|
||||
py::class_<Cage>(m, "Cage");
|
||||
.def("get", &Cage::get);
|
||||
|
||||
You must explicitly specify each template/type combination that you want to
|
||||
wrap separately.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// ok
|
||||
py::class_<Cage<Cat>>(m, "CatCage")
|
||||
.def("get", &Cage<Cat>::get);
|
||||
|
||||
// ok
|
||||
py::class_<Cage<Dog>>(m, "DogCage")
|
||||
.def("get", &Cage<Dog>::get);
|
||||
|
||||
If your class methods have template parameters you can wrap those as well,
|
||||
but once again each instantiation must be explicitly specified:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typename <typename T>
|
||||
struct MyClass {
|
||||
template <typename V>
|
||||
T fn(V v);
|
||||
};
|
||||
|
||||
py::class<MyClass<int>>(m, "MyClassT")
|
||||
.def("fn", &MyClass<int>::fn<std::string>);
|
||||
|
||||
Custom automatic downcasters
|
||||
============================
|
||||
|
||||
@ -1188,7 +1228,7 @@ whether a downcast is safe, you can proceed by specializing the
|
||||
std::string bark() const { return sound; }
|
||||
};
|
||||
|
||||
namespace pybind11 {
|
||||
namespace PYBIND11_NAMESPACE {
|
||||
template<> struct polymorphic_type_hook<Pet> {
|
||||
static const void *get(const Pet *src, const std::type_info*& type) {
|
||||
// note that src may be nullptr
|
||||
@ -1199,7 +1239,7 @@ whether a downcast is safe, you can proceed by specializing the
|
||||
return src;
|
||||
}
|
||||
};
|
||||
} // namespace pybind11
|
||||
} // namespace PYBIND11_NAMESPACE
|
||||
|
||||
When pybind11 wants to convert a C++ pointer of type ``Base*`` to a
|
||||
Python object, it calls ``polymorphic_type_hook<Base>::get()`` to
|
||||
@ -1247,7 +1287,7 @@ Accessing the type object
|
||||
|
||||
You can get the type object from a C++ class that has already been registered using:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: cpp
|
||||
|
||||
py::type T_py = py::type::of<T>();
|
||||
|
||||
@ -1259,3 +1299,37 @@ object, just like ``type(ob)`` in Python.
|
||||
Other types, like ``py::type::of<int>()``, do not work, see :ref:`type-conversions`.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
Custom type setup
|
||||
=================
|
||||
|
||||
For advanced use cases, such as enabling garbage collection support, you may
|
||||
wish to directly manipulate the ``PyHeapTypeObject`` corresponding to a
|
||||
``py::class_`` definition.
|
||||
|
||||
You can do that using ``py::custom_type_setup``:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
struct OwnsPythonObjects {
|
||||
py::object value = py::none();
|
||||
};
|
||||
py::class_<OwnsPythonObjects> cls(
|
||||
m, "OwnsPythonObjects", py::custom_type_setup([](PyHeapTypeObject *heap_type) {
|
||||
auto *type = &heap_type->ht_type;
|
||||
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
|
||||
type->tp_traverse = [](PyObject *self_base, visitproc visit, void *arg) {
|
||||
auto &self = py::cast<OwnsPythonObjects&>(py::handle(self_base));
|
||||
Py_VISIT(self.value.ptr());
|
||||
return 0;
|
||||
};
|
||||
type->tp_clear = [](PyObject *self_base) {
|
||||
auto &self = py::cast<OwnsPythonObjects&>(py::handle(self_base));
|
||||
self.value = py::none();
|
||||
return 0;
|
||||
};
|
||||
}));
|
||||
cls.def(py::init<>());
|
||||
cls.def_readwrite("value", &OwnsPythonObjects::value);
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
27
3rdparty/pybind11/docs/advanced/embedding.rst
vendored
27
3rdparty/pybind11/docs/advanced/embedding.rst
vendored
@ -40,15 +40,15 @@ The essential structure of the ``main.cpp`` file looks like this:
|
||||
}
|
||||
|
||||
The interpreter must be initialized before using any Python API, which includes
|
||||
all the functions and classes in pybind11. The RAII guard class `scoped_interpreter`
|
||||
all the functions and classes in pybind11. The RAII guard class ``scoped_interpreter``
|
||||
takes care of the interpreter lifetime. After the guard is destroyed, the interpreter
|
||||
shuts down and clears its memory. No Python functions can be called after this.
|
||||
|
||||
Executing Python code
|
||||
=====================
|
||||
|
||||
There are a few different ways to run Python code. One option is to use `eval`,
|
||||
`exec` or `eval_file`, as explained in :ref:`eval`. Here is a quick example in
|
||||
There are a few different ways to run Python code. One option is to use ``eval``,
|
||||
``exec`` or ``eval_file``, as explained in :ref:`eval`. Here is a quick example in
|
||||
the context of an executable with an embedded interpreter:
|
||||
|
||||
.. code-block:: cpp
|
||||
@ -108,7 +108,7 @@ The two approaches can also be combined:
|
||||
Importing modules
|
||||
=================
|
||||
|
||||
Python modules can be imported using `module_::import()`:
|
||||
Python modules can be imported using ``module_::import()``:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@ -122,6 +122,7 @@ embedding the interpreter. This makes it easy to import local Python files:
|
||||
|
||||
"""calc.py located in the working directory"""
|
||||
|
||||
|
||||
def add(i, j):
|
||||
return i + j
|
||||
|
||||
@ -133,7 +134,7 @@ embedding the interpreter. This makes it easy to import local Python files:
|
||||
int n = result.cast<int>();
|
||||
assert(n == 3);
|
||||
|
||||
Modules can be reloaded using `module_::reload()` if the source is modified e.g.
|
||||
Modules can be reloaded using ``module_::reload()`` if the source is modified e.g.
|
||||
by an external process. This can be useful in scenarios where the application
|
||||
imports a user defined data processing script which needs to be updated after
|
||||
changes by the user. Note that this function does not reload modules recursively.
|
||||
@ -143,7 +144,7 @@ changes by the user. Note that this function does not reload modules recursively
|
||||
Adding embedded modules
|
||||
=======================
|
||||
|
||||
Embedded binary modules can be added using the `PYBIND11_EMBEDDED_MODULE` macro.
|
||||
Embedded binary modules can be added using the ``PYBIND11_EMBEDDED_MODULE`` macro.
|
||||
Note that the definition must be placed at global scope. They can be imported
|
||||
like any other module.
|
||||
|
||||
@ -169,7 +170,7 @@ like any other module.
|
||||
|
||||
Unlike extension modules where only a single binary module can be created, on
|
||||
the embedded side an unlimited number of modules can be added using multiple
|
||||
`PYBIND11_EMBEDDED_MODULE` definitions (as long as they have unique names).
|
||||
``PYBIND11_EMBEDDED_MODULE`` definitions (as long as they have unique names).
|
||||
|
||||
These modules are added to Python's list of builtins, so they can also be
|
||||
imported in pure Python files loaded by the interpreter. Everything interacts
|
||||
@ -215,9 +216,9 @@ naturally:
|
||||
Interpreter lifetime
|
||||
====================
|
||||
|
||||
The Python interpreter shuts down when `scoped_interpreter` is destroyed. After
|
||||
The Python interpreter shuts down when ``scoped_interpreter`` is destroyed. After
|
||||
this, creating a new instance will restart the interpreter. Alternatively, the
|
||||
`initialize_interpreter` / `finalize_interpreter` pair of functions can be used
|
||||
``initialize_interpreter`` / ``finalize_interpreter`` pair of functions can be used
|
||||
to directly set the state at any time.
|
||||
|
||||
Modules created with pybind11 can be safely re-initialized after the interpreter
|
||||
@ -229,8 +230,8 @@ global data. All the details can be found in the CPython documentation.
|
||||
|
||||
.. warning::
|
||||
|
||||
Creating two concurrent `scoped_interpreter` guards is a fatal error. So is
|
||||
calling `initialize_interpreter` for a second time after the interpreter
|
||||
Creating two concurrent ``scoped_interpreter`` guards is a fatal error. So is
|
||||
calling ``initialize_interpreter`` for a second time after the interpreter
|
||||
has already been initialized.
|
||||
|
||||
Do not use the raw CPython API functions ``Py_Initialize`` and
|
||||
@ -241,7 +242,7 @@ global data. All the details can be found in the CPython documentation.
|
||||
Sub-interpreter support
|
||||
=======================
|
||||
|
||||
Creating multiple copies of `scoped_interpreter` is not possible because it
|
||||
Creating multiple copies of ``scoped_interpreter`` is not possible because it
|
||||
represents the main Python interpreter. Sub-interpreters are something different
|
||||
and they do permit the existence of multiple interpreters. This is an advanced
|
||||
feature of the CPython API and should be handled with care. pybind11 does not
|
||||
@ -257,5 +258,5 @@ We'll just mention a couple of caveats the sub-interpreters support in pybind11:
|
||||
2. Managing multiple threads, multiple interpreters and the GIL can be
|
||||
challenging and there are several caveats here, even within the pure
|
||||
CPython API (please refer to the Python docs for details). As for
|
||||
pybind11, keep in mind that `gil_scoped_release` and `gil_scoped_acquire`
|
||||
pybind11, keep in mind that ``gil_scoped_release`` and ``gil_scoped_acquire``
|
||||
do not take sub-interpreters into account.
|
||||
|
132
3rdparty/pybind11/docs/advanced/exceptions.rst
vendored
132
3rdparty/pybind11/docs/advanced/exceptions.rst
vendored
@ -43,18 +43,28 @@ at its exception handler.
|
||||
| | of bounds access in ``__getitem__``, |
|
||||
| | ``__setitem__``, etc.) |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::value_error` | ``ValueError`` (used to indicate |
|
||||
| | wrong value passed in |
|
||||
| | ``container.remove(...)``) |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::key_error` | ``KeyError`` (used to indicate out |
|
||||
| | of bounds access in ``__getitem__``, |
|
||||
| | ``__setitem__`` in dict-like |
|
||||
| | objects, etc.) |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::value_error` | ``ValueError`` (used to indicate |
|
||||
| | wrong value passed in |
|
||||
| | ``container.remove(...)``) |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::type_error` | ``TypeError`` |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::buffer_error` | ``BufferError`` |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::import_error` | ``ImportError`` |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| :class:`pybind11::attribute_error` | ``AttributeError`` |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
| Any other exception | ``RuntimeError`` |
|
||||
+--------------------------------------+--------------------------------------+
|
||||
|
||||
Exception translation is not bidirectional. That is, *catching* the C++
|
||||
exceptions defined above above will not trap exceptions that originate from
|
||||
exceptions defined above will not trap exceptions that originate from
|
||||
Python. For that, catch :class:`pybind11::error_already_set`. See :ref:`below
|
||||
<handling_python_exceptions_cpp>` for further details.
|
||||
|
||||
@ -67,9 +77,10 @@ Registering custom translators
|
||||
|
||||
If the default exception conversion policy described above is insufficient,
|
||||
pybind11 also provides support for registering custom exception translators.
|
||||
To register a simple exception conversion that translates a C++ exception into
|
||||
a new Python exception using the C++ exception's ``what()`` method, a helper
|
||||
function is available:
|
||||
Similar to pybind11 classes, exception translators can be local to the module
|
||||
they are defined in or global to the entire python session. To register a simple
|
||||
exception conversion that translates a C++ exception into a new Python exception
|
||||
using the C++ exception's ``what()`` method, a helper function is available:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@ -79,29 +90,39 @@ This call creates a Python exception class with the name ``PyExp`` in the given
|
||||
module and automatically converts any encountered exceptions of type ``CppExp``
|
||||
into Python exceptions of type ``PyExp``.
|
||||
|
||||
A matching function is available for registering a local exception translator:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
py::register_local_exception<CppExp>(module, "PyExp");
|
||||
|
||||
|
||||
It is possible to specify base class for the exception using the third
|
||||
parameter, a `handle`:
|
||||
parameter, a ``handle``:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
py::register_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
||||
py::register_local_exception<CppExp>(module, "PyExp", PyExc_RuntimeError);
|
||||
|
||||
Then `PyExp` can be caught both as `PyExp` and `RuntimeError`.
|
||||
Then ``PyExp`` can be caught both as ``PyExp`` and ``RuntimeError``.
|
||||
|
||||
The class objects of the built-in Python exceptions are listed in the Python
|
||||
documentation on `Standard Exceptions <https://docs.python.org/3/c-api/exceptions.html#standard-exceptions>`_.
|
||||
The default base class is `PyExc_Exception`.
|
||||
The default base class is ``PyExc_Exception``.
|
||||
|
||||
When more advanced exception translation is needed, the function
|
||||
``py::register_exception_translator(translator)`` can be used to register
|
||||
When more advanced exception translation is needed, the functions
|
||||
``py::register_exception_translator(translator)`` and
|
||||
``py::register_local_exception_translator(translator)`` can be used to register
|
||||
functions that can translate arbitrary exception types (and which may include
|
||||
additional logic to do so). The function takes a stateless callable (e.g. a
|
||||
additional logic to do so). The functions takes a stateless callable (e.g. a
|
||||
function pointer or a lambda function without captured variables) with the call
|
||||
signature ``void(std::exception_ptr)``.
|
||||
|
||||
When a C++ exception is thrown, the registered exception translators are tried
|
||||
in reverse order of registration (i.e. the last registered translator gets the
|
||||
first shot at handling the exception).
|
||||
first shot at handling the exception). All local translators will be tried
|
||||
before a global translator is tried.
|
||||
|
||||
Inside the translator, ``std::rethrow_exception`` should be used within
|
||||
a try block to re-throw the exception. One or more catch clauses to catch
|
||||
@ -156,6 +177,57 @@ section.
|
||||
may be explicitly (re-)thrown to delegate it to the other,
|
||||
previously-declared existing exception translators.
|
||||
|
||||
Note that ``libc++`` and ``libstdc++`` `behave differently <https://stackoverflow.com/questions/19496643/using-clang-fvisibility-hidden-and-typeinfo-and-type-erasure/28827430>`_
|
||||
with ``-fvisibility=hidden``. Therefore exceptions that are used across ABI boundaries need to be explicitly exported, as exercised in ``tests/test_exceptions.h``.
|
||||
See also: "Problems with C++ exceptions" under `GCC Wiki <https://gcc.gnu.org/wiki/Visibility>`_.
|
||||
|
||||
|
||||
Local vs Global Exception Translators
|
||||
=====================================
|
||||
|
||||
When a global exception translator is registered, it will be applied across all
|
||||
modules in the reverse order of registration. This can create behavior where the
|
||||
order of module import influences how exceptions are translated.
|
||||
|
||||
If module1 has the following translator:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
PyErr_SetString("module1 handled this")
|
||||
}
|
||||
}
|
||||
|
||||
and module2 has the following similar translator:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
} catch (const std::invalid_argument &e) {
|
||||
PyErr_SetString("module2 handled this")
|
||||
}
|
||||
}
|
||||
|
||||
then which translator handles the invalid_argument will be determined by the
|
||||
order that module1 and module2 are imported. Since exception translators are
|
||||
applied in the reverse order of registration, which ever module was imported
|
||||
last will "win" and that translator will be applied.
|
||||
|
||||
If there are multiple pybind11 modules that share exception types (either
|
||||
standard built-in or custom) loaded into a single python instance and
|
||||
consistent error handling behavior is needed, then local translators should be
|
||||
used.
|
||||
|
||||
Changing the previous example to use ``register_local_exception_translator``
|
||||
would mean that when invalid_argument is thrown in the module2 code, the
|
||||
module2 translator will always handle it, while in module1, the module1
|
||||
translator will do the same.
|
||||
|
||||
.. _handling_python_exceptions_cpp:
|
||||
|
||||
Handling exceptions from Python in C++
|
||||
@ -188,7 +260,7 @@ For example:
|
||||
} catch (py::error_already_set &e) {
|
||||
if (e.matches(PyExc_FileNotFoundError)) {
|
||||
py::print("missing.txt not found");
|
||||
} else if (e.match(PyExc_PermissionError)) {
|
||||
} else if (e.matches(PyExc_PermissionError)) {
|
||||
py::print("missing.txt found but not accessible");
|
||||
} else {
|
||||
throw;
|
||||
@ -253,6 +325,34 @@ Alternately, to ignore the error, call `PyErr_Clear
|
||||
Any Python error must be thrown or cleared, or Python/pybind11 will be left in
|
||||
an invalid state.
|
||||
|
||||
Chaining exceptions ('raise from')
|
||||
==================================
|
||||
|
||||
Python has a mechanism for indicating that exceptions were caused by other
|
||||
exceptions:
|
||||
|
||||
.. code-block:: py
|
||||
|
||||
try:
|
||||
print(1 / 0)
|
||||
except Exception as exc:
|
||||
raise RuntimeError("could not divide by zero") from exc
|
||||
|
||||
To do a similar thing in pybind11, you can use the ``py::raise_from`` function. It
|
||||
sets the current python error indicator, so to continue propagating the exception
|
||||
you should ``throw py::error_already_set()``.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
try {
|
||||
py::eval("print(1 / 0"));
|
||||
} catch (py::error_already_set &e) {
|
||||
py::raise_from(e, PyExc_RuntimeError, "could not divide by zero");
|
||||
throw py::error_already_set();
|
||||
}
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
.. _unraisable_exceptions:
|
||||
|
||||
Handling unraisable exceptions
|
||||
|
87
3rdparty/pybind11/docs/advanced/functions.rst
vendored
87
3rdparty/pybind11/docs/advanced/functions.rst
vendored
@ -50,7 +50,7 @@ implied transfer of ownership, i.e.:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
m.def("get_data", &get_data, return_value_policy::reference);
|
||||
m.def("get_data", &get_data, py::return_value_policy::reference);
|
||||
|
||||
On the other hand, this is not the right policy for many other situations,
|
||||
where ignoring ownership could lead to resource leaks.
|
||||
@ -90,17 +90,18 @@ The following table provides an overview of available policies:
|
||||
| | return value is referenced by Python. This is the default policy for |
|
||||
| | property getters created via ``def_property``, ``def_readwrite``, etc. |
|
||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||
| :enum:`return_value_policy::automatic` | **Default policy.** This policy falls back to the policy |
|
||||
| :enum:`return_value_policy::automatic` | This policy falls back to the policy |
|
||||
| | :enum:`return_value_policy::take_ownership` when the return value is a |
|
||||
| | pointer. Otherwise, it uses :enum:`return_value_policy::move` or |
|
||||
| | :enum:`return_value_policy::copy` for rvalue and lvalue references, |
|
||||
| | respectively. See above for a description of what all of these different |
|
||||
| | policies do. |
|
||||
| | policies do. This is the default policy for ``py::class_``-wrapped types. |
|
||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||
| :enum:`return_value_policy::automatic_reference` | As above, but use policy :enum:`return_value_policy::reference` when the |
|
||||
| | return value is a pointer. This is the default conversion policy for |
|
||||
| | function arguments when calling Python functions manually from C++ code |
|
||||
| | (i.e. via handle::operator()). You probably won't need to use this. |
|
||||
| | (i.e. via ``handle::operator()``) and the casters in ``pybind11/stl.h``. |
|
||||
| | You probably won't need to use this explicitly. |
|
||||
+--------------------------------------------------+----------------------------------------------------------------------------+
|
||||
|
||||
Return value policies can also be applied to properties:
|
||||
@ -119,7 +120,7 @@ targeted arguments can be passed through the :class:`cpp_function` constructor:
|
||||
.. code-block:: cpp
|
||||
|
||||
class_<MyClass>(m, "MyClass")
|
||||
.def_property("data"
|
||||
.def_property("data",
|
||||
py::cpp_function(&MyClass::getData, py::return_value_policy::copy),
|
||||
py::cpp_function(&MyClass::setData)
|
||||
);
|
||||
@ -182,6 +183,9 @@ relies on the ability to create a *weak reference* to the nurse object. When
|
||||
the nurse object is not a pybind11-registered type and does not support weak
|
||||
references, an exception will be thrown.
|
||||
|
||||
If you use an incorrect argument index, you will get a ``RuntimeError`` saying
|
||||
``Could not activate keep_alive!``. You should review the indices you're using.
|
||||
|
||||
Consider the following example: here, the binding code for a list append
|
||||
operation ties the lifetime of the newly added element to the underlying
|
||||
container:
|
||||
@ -228,7 +232,7 @@ is equivalent to the following pseudocode:
|
||||
});
|
||||
|
||||
The only requirement is that ``T`` is default-constructible, but otherwise any
|
||||
scope guard will work. This is very useful in combination with `gil_scoped_release`.
|
||||
scope guard will work. This is very useful in combination with ``gil_scoped_release``.
|
||||
See :ref:`gil`.
|
||||
|
||||
Multiple guards can also be specified as ``py::call_guard<T1, T2, T3...>``. The
|
||||
@ -251,7 +255,7 @@ For instance, the following statement iterates over a Python ``dict``:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void print_dict(py::dict dict) {
|
||||
void print_dict(const py::dict& dict) {
|
||||
/* Easily interact with Python types */
|
||||
for (auto item : dict)
|
||||
std::cout << "key=" << std::string(py::str(item.first)) << ", "
|
||||
@ -268,7 +272,7 @@ And used in Python as usual:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> print_dict({'foo': 123, 'bar': 'hello'})
|
||||
>>> print_dict({"foo": 123, "bar": "hello"})
|
||||
key=foo, value=123
|
||||
key=bar, value=hello
|
||||
|
||||
@ -289,7 +293,7 @@ Such functions can also be created using pybind11:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void generic(py::args args, py::kwargs kwargs) {
|
||||
void generic(py::args args, const py::kwargs& kwargs) {
|
||||
/// .. do something with args
|
||||
if (kwargs)
|
||||
/// .. do something with kwargs
|
||||
@ -302,8 +306,9 @@ The class ``py::args`` derives from ``py::tuple`` and ``py::kwargs`` derives
|
||||
from ``py::dict``.
|
||||
|
||||
You may also use just one or the other, and may combine these with other
|
||||
arguments as long as the ``py::args`` and ``py::kwargs`` arguments are the last
|
||||
arguments accepted by the function.
|
||||
arguments. Note, however, that ``py::kwargs`` must always be the last argument
|
||||
of the function, and ``py::args`` implies that any further arguments are
|
||||
keyword-only (see :ref:`keyword_only_arguments`).
|
||||
|
||||
Please refer to the other examples for details on how to iterate over these,
|
||||
and on how to cast their entries into C++ objects. A demonstration is also
|
||||
@ -362,10 +367,12 @@ like so:
|
||||
py::class_<MyClass>("MyClass")
|
||||
.def("myFunction", py::arg("arg") = static_cast<SomeType *>(nullptr));
|
||||
|
||||
.. _keyword_only_arguments:
|
||||
|
||||
Keyword-only arguments
|
||||
======================
|
||||
|
||||
Python 3 introduced keyword-only arguments by specifying an unnamed ``*``
|
||||
Python implements keyword-only arguments by specifying an unnamed ``*``
|
||||
argument in a function definition:
|
||||
|
||||
.. code-block:: python
|
||||
@ -373,10 +380,11 @@ argument in a function definition:
|
||||
def f(a, *, b): # a can be positional or via keyword; b must be via keyword
|
||||
pass
|
||||
|
||||
|
||||
f(a=1, b=2) # good
|
||||
f(b=2, a=1) # good
|
||||
f(1, b=2) # good
|
||||
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
|
||||
f(1, b=2) # good
|
||||
f(1, 2) # TypeError: f() takes 1 positional argument but 2 were given
|
||||
|
||||
Pybind11 provides a ``py::kw_only`` object that allows you to implement
|
||||
the same behaviour by specifying the object between positional and keyword-only
|
||||
@ -387,11 +395,19 @@ argument annotations when registering the function:
|
||||
m.def("f", [](int a, int b) { /* ... */ },
|
||||
py::arg("a"), py::kw_only(), py::arg("b"));
|
||||
|
||||
Note that you currently cannot combine this with a ``py::args`` argument. This
|
||||
feature does *not* require Python 3 to work.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
A ``py::args`` argument implies that any following arguments are keyword-only,
|
||||
as if ``py::kw_only()`` had been specified in the same relative location of the
|
||||
argument list as the ``py::args`` argument. The ``py::kw_only()`` may be
|
||||
included to be explicit about this, but is not required.
|
||||
|
||||
.. versionchanged:: 2.9
|
||||
This can now be combined with ``py::args``. Before, ``py::args`` could only
|
||||
occur at the end of the argument list, or immediately before a ``py::kwargs``
|
||||
argument at the end.
|
||||
|
||||
|
||||
Positional-only arguments
|
||||
=========================
|
||||
|
||||
@ -524,6 +540,8 @@ The default behaviour when the tag is unspecified is to allow ``None``.
|
||||
not allow ``None`` as argument. To pass optional argument of these copied types consider
|
||||
using ``std::optional<T>``
|
||||
|
||||
.. _overload_resolution:
|
||||
|
||||
Overload resolution order
|
||||
=========================
|
||||
|
||||
@ -559,3 +577,38 @@ prefers earlier-defined overloads to later-defined ones.
|
||||
.. versionadded:: 2.6
|
||||
|
||||
The ``py::prepend()`` tag.
|
||||
|
||||
Binding functions with template parameters
|
||||
==========================================
|
||||
|
||||
You can bind functions that have template parameters. Here's a function:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
template <typename T>
|
||||
void set(T t);
|
||||
|
||||
C++ templates cannot be instantiated at runtime, so you cannot bind the
|
||||
non-instantiated function:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
// BROKEN (this will not compile)
|
||||
m.def("set", &set);
|
||||
|
||||
You must bind each instantiated function template separately. You may bind
|
||||
each instantiation with the same name, which will be treated the same as
|
||||
an overloaded function:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
m.def("set", &set<int>);
|
||||
m.def("set", &set<std::string>);
|
||||
|
||||
Sometimes it's more clear to bind them with separate names, which is also
|
||||
an option:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
m.def("setInt", &set<int>);
|
||||
m.def("setString", &set<std::string>);
|
||||
|
2
3rdparty/pybind11/docs/advanced/misc.rst
vendored
2
3rdparty/pybind11/docs/advanced/misc.rst
vendored
@ -84,7 +84,7 @@ could be realized as follows (important changes highlighted):
|
||||
});
|
||||
}
|
||||
|
||||
The ``call_go`` wrapper can also be simplified using the `call_guard` policy
|
||||
The ``call_go`` wrapper can also be simplified using the ``call_guard`` policy
|
||||
(see :ref:`call_policies`) which yields the same result:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
67
3rdparty/pybind11/docs/advanced/pycpp/numpy.rst
vendored
67
3rdparty/pybind11/docs/advanced/pycpp/numpy.rst
vendored
@ -87,7 +87,7 @@ buffer objects (e.g. a NumPy matrix).
|
||||
/* Request a buffer descriptor from Python */
|
||||
py::buffer_info info = b.request();
|
||||
|
||||
/* Some sanity checks ... */
|
||||
/* Some basic validation checks ... */
|
||||
if (info.format != py::format_descriptor<Scalar>::format())
|
||||
throw std::runtime_error("Incompatible format: expected a double array!");
|
||||
|
||||
@ -150,8 +150,10 @@ NumPy array containing double precision values.
|
||||
|
||||
When it is invoked with a different type (e.g. an integer or a list of
|
||||
integers), the binding code will attempt to cast the input into a NumPy array
|
||||
of the requested type. Note that this feature requires the
|
||||
:file:`pybind11/numpy.h` header to be included.
|
||||
of the requested type. This feature requires the :file:`pybind11/numpy.h`
|
||||
header to be included. Note that :file:`pybind11/numpy.h` does not depend on
|
||||
the NumPy headers, and thus can be used without declaring a build-time
|
||||
dependency on NumPy; NumPy>=1.7.0 is a runtime dependency.
|
||||
|
||||
Data in NumPy arrays is not guaranteed to packed in a dense manner;
|
||||
furthermore, entries can be separated by arbitrary column and row strides.
|
||||
@ -169,6 +171,31 @@ template parameter, and it ensures that non-conforming arguments are converted
|
||||
into an array satisfying the specified requirements instead of trying the next
|
||||
function overload.
|
||||
|
||||
There are several methods on arrays; the methods listed below under references
|
||||
work, as well as the following functions based on the NumPy API:
|
||||
|
||||
- ``.dtype()`` returns the type of the contained values.
|
||||
|
||||
- ``.strides()`` returns a pointer to the strides of the array (optionally pass
|
||||
an integer axis to get a number).
|
||||
|
||||
- ``.flags()`` returns the flag settings. ``.writable()`` and ``.owndata()``
|
||||
are directly available.
|
||||
|
||||
- ``.offset_at()`` returns the offset (optionally pass indices).
|
||||
|
||||
- ``.squeeze()`` returns a view with length-1 axes removed.
|
||||
|
||||
- ``.view(dtype)`` returns a view of the array with a different dtype.
|
||||
|
||||
- ``.reshape({i, j, ...})`` returns a view of the array with a different shape.
|
||||
``.resize({...})`` is also available.
|
||||
|
||||
- ``.index_at(i, j, ...)`` gets the count from the beginning to a given index.
|
||||
|
||||
|
||||
There are also several methods for getting references (described below).
|
||||
|
||||
Structured types
|
||||
================
|
||||
|
||||
@ -231,8 +258,8 @@ by the compiler. The result is returned as a NumPy array of type
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> x = np.array([[1, 3],[5, 7]])
|
||||
>>> y = np.array([[2, 4],[6, 8]])
|
||||
>>> x = np.array([[1, 3], [5, 7]])
|
||||
>>> y = np.array([[2, 4], [6, 8]])
|
||||
>>> z = 3
|
||||
>>> result = vectorized_func(x, y, z)
|
||||
|
||||
@ -343,21 +370,21 @@ The returned proxy object supports some of the same methods as ``py::array`` so
|
||||
that it can be used as a drop-in replacement for some existing, index-checked
|
||||
uses of ``py::array``:
|
||||
|
||||
- ``r.ndim()`` returns the number of dimensions
|
||||
- ``.ndim()`` returns the number of dimensions
|
||||
|
||||
- ``r.data(1, 2, ...)`` and ``r.mutable_data(1, 2, ...)``` returns a pointer to
|
||||
- ``.data(1, 2, ...)`` and ``r.mutable_data(1, 2, ...)``` returns a pointer to
|
||||
the ``const T`` or ``T`` data, respectively, at the given indices. The
|
||||
latter is only available to proxies obtained via ``a.mutable_unchecked()``.
|
||||
|
||||
- ``itemsize()`` returns the size of an item in bytes, i.e. ``sizeof(T)``.
|
||||
- ``.itemsize()`` returns the size of an item in bytes, i.e. ``sizeof(T)``.
|
||||
|
||||
- ``ndim()`` returns the number of dimensions.
|
||||
- ``.ndim()`` returns the number of dimensions.
|
||||
|
||||
- ``shape(n)`` returns the size of dimension ``n``
|
||||
- ``.shape(n)`` returns the size of dimension ``n``
|
||||
|
||||
- ``size()`` returns the total number of elements (i.e. the product of the shapes).
|
||||
- ``.size()`` returns the total number of elements (i.e. the product of the shapes).
|
||||
|
||||
- ``nbytes()`` returns the number of bytes used by the referenced elements
|
||||
- ``.nbytes()`` returns the number of bytes used by the referenced elements
|
||||
(i.e. ``itemsize()`` times ``size()``).
|
||||
|
||||
.. seealso::
|
||||
@ -368,15 +395,13 @@ uses of ``py::array``:
|
||||
Ellipsis
|
||||
========
|
||||
|
||||
Python 3 provides a convenient ``...`` ellipsis notation that is often used to
|
||||
Python provides a convenient ``...`` ellipsis notation that is often used to
|
||||
slice multidimensional arrays. For instance, the following snippet extracts the
|
||||
middle dimensions of a tensor with the first and last index set to zero.
|
||||
In Python 2, the syntactic sugar ``...`` is not available, but the singleton
|
||||
``Ellipsis`` (of type ``ellipsis``) can still be used directly.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
a = # a NumPy array
|
||||
a = ... # a NumPy array
|
||||
b = a[0, ..., 0]
|
||||
|
||||
The function ``py::ellipsis()`` function can be used to perform the same
|
||||
@ -387,8 +412,6 @@ operation on the C++ side:
|
||||
py::array a = /* A NumPy array */;
|
||||
py::array b = a[py::make_tuple(0, py::ellipsis(), 0)];
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
``py::ellipsis()`` is now also avaliable in Python 2.
|
||||
|
||||
Memory view
|
||||
===========
|
||||
@ -410,7 +433,7 @@ following:
|
||||
{ 2, 4 }, // shape (rows, cols)
|
||||
{ sizeof(uint8_t) * 4, sizeof(uint8_t) } // strides in bytes
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
This approach is meant for providing a ``memoryview`` for a C/C++ buffer not
|
||||
managed by Python. The user is responsible for managing the lifetime of the
|
||||
@ -426,11 +449,7 @@ We can also use ``memoryview::from_memory`` for a simple 1D contiguous buffer:
|
||||
buffer, // buffer pointer
|
||||
sizeof(uint8_t) * 8 // buffer size
|
||||
);
|
||||
})
|
||||
|
||||
.. note::
|
||||
|
||||
``memoryview::from_memory`` is not available in Python 2.
|
||||
});
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
``memoryview::from_memory`` added.
|
||||
|
37
3rdparty/pybind11/docs/advanced/pycpp/object.rst
vendored
37
3rdparty/pybind11/docs/advanced/pycpp/object.rst
vendored
@ -20,6 +20,40 @@ Available types include :class:`handle`, :class:`object`, :class:`bool_`,
|
||||
Be sure to review the :ref:`pytypes_gotchas` before using this heavily in
|
||||
your C++ API.
|
||||
|
||||
.. _instantiating_compound_types:
|
||||
|
||||
Instantiating compound Python types from C++
|
||||
============================================
|
||||
|
||||
Dictionaries can be initialized in the :class:`dict` constructor:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
using namespace pybind11::literals; // to bring in the `_a` literal
|
||||
py::dict d("spam"_a=py::none(), "eggs"_a=42);
|
||||
|
||||
A tuple of python objects can be instantiated using :func:`py::make_tuple`:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
py::tuple tup = py::make_tuple(42, py::none(), "spam");
|
||||
|
||||
Each element is converted to a supported Python type.
|
||||
|
||||
A `simple namespace`_ can be instantiated using
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
using namespace pybind11::literals; // to bring in the `_a` literal
|
||||
py::object SimpleNamespace = py::module_::import("types").attr("SimpleNamespace");
|
||||
py::object ns = SimpleNamespace("spam"_a=py::none(), "eggs"_a=42);
|
||||
|
||||
Attributes on a namespace can be modified with the :func:`py::delattr`,
|
||||
:func:`py::getattr`, and :func:`py::setattr` functions. Simple namespaces can
|
||||
be useful as lightweight stand-ins for class instances.
|
||||
|
||||
.. _simple namespace: https://docs.python.org/3/library/types.html#types.SimpleNamespace
|
||||
|
||||
.. _casting_back_and_forth:
|
||||
|
||||
Casting back and forth
|
||||
@ -30,7 +64,7 @@ types to Python, which can be done using :func:`py::cast`:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
MyClass *cls = ..;
|
||||
MyClass *cls = ...;
|
||||
py::object obj = py::cast(cls);
|
||||
|
||||
The reverse direction uses the following syntax:
|
||||
@ -132,6 +166,7 @@ Keyword arguments are also supported. In Python, there is the usual call syntax:
|
||||
def f(number, say, to):
|
||||
... # function code
|
||||
|
||||
|
||||
f(1234, say="hello", to=some_instance) # keyword call in Python
|
||||
|
||||
In C++, the same call can be made using:
|
||||
|
@ -28,7 +28,7 @@ Capturing standard output from ostream
|
||||
|
||||
Often, a library will use the streams ``std::cout`` and ``std::cerr`` to print,
|
||||
but this does not play well with Python's standard ``sys.stdout`` and ``sys.stderr``
|
||||
redirection. Replacing a library's printing with `py::print <print>` may not
|
||||
redirection. Replacing a library's printing with ``py::print <print>`` may not
|
||||
be feasible. This can be fixed using a guard around the library function that
|
||||
redirects output to the corresponding Python streams:
|
||||
|
||||
@ -47,15 +47,26 @@ redirects output to the corresponding Python streams:
|
||||
call_noisy_func();
|
||||
});
|
||||
|
||||
.. warning::
|
||||
|
||||
The implementation in ``pybind11/iostream.h`` is NOT thread safe. Multiple
|
||||
threads writing to a redirected ostream concurrently cause data races
|
||||
and potentially buffer overflows. Therefore it is currently a requirement
|
||||
that all (possibly) concurrent redirected ostream writes are protected by
|
||||
a mutex. #HelpAppreciated: Work on iostream.h thread safety. For more
|
||||
background see the discussions under
|
||||
`PR #2982 <https://github.com/pybind/pybind11/pull/2982>`_ and
|
||||
`PR #2995 <https://github.com/pybind/pybind11/pull/2995>`_.
|
||||
|
||||
This method respects flushes on the output streams and will flush if needed
|
||||
when the scoped guard is destroyed. This allows the output to be redirected in
|
||||
real time, such as to a Jupyter notebook. The two arguments, the C++ stream and
|
||||
the Python output, are optional, and default to standard output if not given. An
|
||||
extra type, `py::scoped_estream_redirect <scoped_estream_redirect>`, is identical
|
||||
extra type, ``py::scoped_estream_redirect <scoped_estream_redirect>``, is identical
|
||||
except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful with
|
||||
`py::call_guard`, which allows multiple items, but uses the default constructor:
|
||||
``py::call_guard``, which allows multiple items, but uses the default constructor:
|
||||
|
||||
.. code-block:: py
|
||||
.. code-block:: cpp
|
||||
|
||||
// Alternative: Call single function using call guard
|
||||
m.def("noisy_func", &call_noisy_function,
|
||||
@ -63,7 +74,7 @@ except for defaulting to ``std::cerr`` and ``sys.stderr``; this can be useful wi
|
||||
py::scoped_estream_redirect>());
|
||||
|
||||
The redirection can also be done in Python with the addition of a context
|
||||
manager, using the `py::add_ostream_redirect() <add_ostream_redirect>` function:
|
||||
manager, using the ``py::add_ostream_redirect() <add_ostream_redirect>`` function:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@ -92,7 +103,7 @@ arguments to disable one of the streams if needed.
|
||||
Evaluating Python expressions from strings and files
|
||||
====================================================
|
||||
|
||||
pybind11 provides the `eval`, `exec` and `eval_file` functions to evaluate
|
||||
pybind11 provides the ``eval``, ``exec`` and ``eval_file`` functions to evaluate
|
||||
Python expressions and statements. The following example illustrates how they
|
||||
can be used.
|
||||
|
||||
|
@ -77,6 +77,7 @@ segmentation fault).
|
||||
.. code-block:: python
|
||||
|
||||
from example import Parent
|
||||
|
||||
print(Parent().get_child())
|
||||
|
||||
The problem is that ``Parent::get_child()`` returns a pointer to an instance of
|
||||
@ -156,7 +157,7 @@ specialized:
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
|
||||
|
||||
// Only needed if the type's `.get()` goes by another name
|
||||
namespace pybind11 { namespace detail {
|
||||
namespace PYBIND11_NAMESPACE { namespace detail {
|
||||
template <typename T>
|
||||
struct holder_helper<SmartPtr<T>> { // <-- specialization
|
||||
static const T *get(const SmartPtr<T> &p) { return p.getPointer(); }
|
||||
|
20
3rdparty/pybind11/docs/basics.rst
vendored
20
3rdparty/pybind11/docs/basics.rst
vendored
@ -32,8 +32,7 @@ The last line will both compile and run the tests.
|
||||
Windows
|
||||
-------
|
||||
|
||||
On Windows, only **Visual Studio 2015** and newer are supported since pybind11 relies
|
||||
on various C++11 language features that break older versions of Visual Studio.
|
||||
On Windows, only **Visual Studio 2017** and newer are supported.
|
||||
|
||||
.. Note::
|
||||
|
||||
@ -109,7 +108,7 @@ a file named :file:`example.cpp` with the following contents:
|
||||
PYBIND11_MODULE(example, m) {
|
||||
m.doc() = "pybind11 example plugin"; // optional module docstring
|
||||
|
||||
m.def("add", &add, "A function which adds two numbers");
|
||||
m.def("add", &add, "A function that adds two numbers");
|
||||
}
|
||||
|
||||
.. [#f1] In practice, implementation and binding code will generally be located
|
||||
@ -136,7 +135,14 @@ On Linux, the above example can be compiled using the following command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`
|
||||
$ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
|
||||
|
||||
.. note::
|
||||
|
||||
If you used :ref:`include_as_a_submodule` to get the pybind11 source, then
|
||||
use ``$(python3-config --includes) -Iextern/pybind11/include`` instead of
|
||||
``$(python3 -m pybind11 --includes)`` in the above compilation, as
|
||||
explained in :ref:`building_manually`.
|
||||
|
||||
For more details on the required compiler flags on Linux and macOS, see
|
||||
:ref:`building_manually`. For complete cross-platform compilation instructions,
|
||||
@ -159,12 +165,12 @@ load and execute the example:
|
||||
.. code-block:: pycon
|
||||
|
||||
$ python
|
||||
Python 2.7.10 (default, Aug 22 2015, 20:33:39)
|
||||
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)] on darwin
|
||||
Python 3.9.10 (main, Jan 15 2022, 11:48:04)
|
||||
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> import example
|
||||
>>> example.add(1, 2)
|
||||
3L
|
||||
3
|
||||
>>>
|
||||
|
||||
.. _keyword_args:
|
||||
|
33
3rdparty/pybind11/docs/benchmark.py
vendored
33
3rdparty/pybind11/docs/benchmark.py
vendored
@ -1,8 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import random
|
||||
import os
|
||||
import time
|
||||
import datetime as dt
|
||||
import os
|
||||
import random
|
||||
|
||||
nfns = 4 # Functions per class
|
||||
nargs = 4 # Arguments per function
|
||||
@ -13,20 +11,20 @@ def generate_dummy_code_pybind11(nclasses=10):
|
||||
bindings = ""
|
||||
|
||||
for cl in range(nclasses):
|
||||
decl += "class cl%03i;\n" % cl
|
||||
decl += f"class cl{cl:03};\n"
|
||||
decl += "\n"
|
||||
|
||||
for cl in range(nclasses):
|
||||
decl += "class cl%03i {\n" % cl
|
||||
decl += f"class {cl:03} {{\n"
|
||||
decl += "public:\n"
|
||||
bindings += ' py::class_<cl%03i>(m, "cl%03i")\n' % (cl, cl)
|
||||
bindings += f' py::class_<cl{cl:03}>(m, "cl{cl:03}")\n'
|
||||
for fn in range(nfns):
|
||||
ret = random.randint(0, nclasses - 1)
|
||||
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
||||
decl += " cl%03i *fn_%03i(" % (ret, fn)
|
||||
decl += ", ".join("cl%03i *" % p for p in params)
|
||||
decl += f" cl{ret:03} *fn_{fn:03}("
|
||||
decl += ", ".join(f"cl{p:03} *" for p in params)
|
||||
decl += ");\n"
|
||||
bindings += ' .def("fn_%03i", &cl%03i::fn_%03i)\n' % (fn, cl, fn)
|
||||
bindings += f' .def("fn_{fn:03}", &cl{cl:03}::fn_{fn:03})\n'
|
||||
decl += "};\n\n"
|
||||
bindings += " ;\n"
|
||||
|
||||
@ -44,23 +42,20 @@ def generate_dummy_code_boost(nclasses=10):
|
||||
bindings = ""
|
||||
|
||||
for cl in range(nclasses):
|
||||
decl += "class cl%03i;\n" % cl
|
||||
decl += f"class cl{cl:03};\n"
|
||||
decl += "\n"
|
||||
|
||||
for cl in range(nclasses):
|
||||
decl += "class cl%03i {\n" % cl
|
||||
decl += "public:\n"
|
||||
bindings += ' py::class_<cl%03i>("cl%03i")\n' % (cl, cl)
|
||||
bindings += f' py::class_<cl{cl:03}>("cl{cl:03}")\n'
|
||||
for fn in range(nfns):
|
||||
ret = random.randint(0, nclasses - 1)
|
||||
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
||||
decl += " cl%03i *fn_%03i(" % (ret, fn)
|
||||
decl += ", ".join("cl%03i *" % p for p in params)
|
||||
decl += f" cl{ret:03} *fn_{fn:03}("
|
||||
decl += ", ".join(f"cl{p:03} *" for p in params)
|
||||
decl += ");\n"
|
||||
bindings += (
|
||||
' .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy<py::manage_new_object>())\n'
|
||||
% (fn, cl, fn)
|
||||
)
|
||||
bindings += f' .def("fn_{fn:03}", &cl{cl:03}::fn_{fn:03}, py::return_value_policy<py::manage_new_object>())\n'
|
||||
decl += "};\n\n"
|
||||
bindings += " ;\n"
|
||||
|
||||
@ -76,7 +71,7 @@ def generate_dummy_code_boost(nclasses=10):
|
||||
for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]:
|
||||
print("{")
|
||||
for i in range(0, 10):
|
||||
nclasses = 2 ** i
|
||||
nclasses = 2**i
|
||||
with open("test.cpp", "w") as f:
|
||||
f.write(codegen(nclasses))
|
||||
n1 = dt.datetime.now()
|
||||
|
934
3rdparty/pybind11/docs/changelog.rst
vendored
934
3rdparty/pybind11/docs/changelog.rst
vendored
@ -6,6 +6,931 @@ Changelog
|
||||
Starting with version 1.8.0, pybind11 releases use a `semantic versioning
|
||||
<http://semver.org>`_ policy.
|
||||
|
||||
Changes will be added here periodically from the "Suggested changelog entry"
|
||||
block in pull request descriptions.
|
||||
|
||||
|
||||
|
||||
IN DEVELOPMENT
|
||||
--------------
|
||||
|
||||
Changes will be summarized here periodically.
|
||||
|
||||
Version 2.10.0 (Jul 15, 2022)
|
||||
-----------------------------
|
||||
|
||||
Removed support for Python 2.7, Python 3.5, and MSVC 2015. Support for MSVC
|
||||
2017 is limited due to availability of CI runners; we highly recommend MSVC
|
||||
2019 or 2022 be used. Initial support added for Python 3.11.
|
||||
|
||||
New features:
|
||||
|
||||
* ``py::anyset`` & ``py::frozenset`` were added, with copying (cast) to
|
||||
``std::set`` (similar to ``set``).
|
||||
`#3901 <https://github.com/pybind/pybind11/pull/3901>`_
|
||||
|
||||
* Support bytearray casting to string.
|
||||
`#3707 <https://github.com/pybind/pybind11/pull/3707>`_
|
||||
|
||||
* ``type_caster<std::monostate>`` was added. ``std::monostate`` is a tag type
|
||||
that allows ``std::variant`` to act as an optional, or allows default
|
||||
construction of a ``std::variant`` holding a non-default constructible type.
|
||||
`#3818 <https://github.com/pybind/pybind11/pull/3818>`_
|
||||
|
||||
* ``pybind11::capsule::set_name`` added to mutate the name of the capsule instance.
|
||||
`#3866 <https://github.com/pybind/pybind11/pull/3866>`_
|
||||
|
||||
* NumPy: dtype constructor from type number added, accessors corresponding to
|
||||
Python API ``dtype.num``, ``dtype.byteorder``, ``dtype.flags`` and
|
||||
``dtype.alignment`` added.
|
||||
`#3868 <https://github.com/pybind/pybind11/pull/3868>`_
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
* Python 3.6 is now the minimum supported version.
|
||||
`#3688 <https://github.com/pybind/pybind11/pull/3688>`_
|
||||
`#3719 <https://github.com/pybind/pybind11/pull/3719>`_
|
||||
|
||||
* The minimum version for MSVC is now 2017.
|
||||
`#3722 <https://github.com/pybind/pybind11/pull/3722>`_
|
||||
|
||||
* Fix issues with CPython 3.11 betas and add to supported test matrix.
|
||||
`#3923 <https://github.com/pybind/pybind11/pull/3923>`_
|
||||
|
||||
* ``error_already_set`` is now safer and more performant, especially for
|
||||
exceptions with long tracebacks, by delaying computation.
|
||||
`#1895 <https://github.com/pybind/pybind11/pull/1895>`_
|
||||
|
||||
* Improve exception handling in python ``str`` bindings.
|
||||
`#3826 <https://github.com/pybind/pybind11/pull/3826>`_
|
||||
|
||||
* The bindings for capsules now have more consistent exception handling.
|
||||
`#3825 <https://github.com/pybind/pybind11/pull/3825>`_
|
||||
|
||||
* ``PYBIND11_OBJECT_CVT`` and ``PYBIND11_OBJECT_CVT_DEFAULT`` macro can now be
|
||||
used to define classes in namespaces other than pybind11.
|
||||
`#3797 <https://github.com/pybind/pybind11/pull/3797>`_
|
||||
|
||||
* Error printing code now uses ``PYBIND11_DETAILED_ERROR_MESSAGES`` instead of
|
||||
requiring ``NDEBUG``, allowing use with release builds if desired.
|
||||
`#3913 <https://github.com/pybind/pybind11/pull/3913>`_
|
||||
|
||||
* Implicit conversion of the literal ``0`` to ``pybind11::handle`` is now disabled.
|
||||
`#4008 <https://github.com/pybind/pybind11/pull/4008>`_
|
||||
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix exception handling when ``pybind11::weakref()`` fails.
|
||||
`#3739 <https://github.com/pybind/pybind11/pull/3739>`_
|
||||
|
||||
* ``module_::def_submodule`` was missing proper error handling. This is fixed now.
|
||||
`#3973 <https://github.com/pybind/pybind11/pull/3973>`_
|
||||
|
||||
* The behavior or ``error_already_set`` was made safer and the highly opaque
|
||||
"Unknown internal error occurred" message was replaced with a more helpful
|
||||
message.
|
||||
`#3982 <https://github.com/pybind/pybind11/pull/3982>`_
|
||||
|
||||
* ``error_already_set::what()`` now handles non-normalized exceptions correctly.
|
||||
`#3971 <https://github.com/pybind/pybind11/pull/3971>`_
|
||||
|
||||
* Support older C++ compilers where filesystem is not yet part of the standard
|
||||
library and is instead included in ``std::experimental::filesystem``.
|
||||
`#3840 <https://github.com/pybind/pybind11/pull/3840>`_
|
||||
|
||||
* Fix ``-Wfree-nonheap-object`` warnings produced by GCC by avoiding returning
|
||||
pointers to static objects with ``return_value_policy::take_ownership``.
|
||||
`#3946 <https://github.com/pybind/pybind11/pull/3946>`_
|
||||
|
||||
* Fix cast from pytype rvalue to another pytype.
|
||||
`#3949 <https://github.com/pybind/pybind11/pull/3949>`_
|
||||
|
||||
* Ensure proper behavior when garbage collecting classes with dynamic attributes in Python >=3.9.
|
||||
`#4051 <https://github.com/pybind/pybind11/pull/4051>`_
|
||||
|
||||
* A couple long-standing ``PYBIND11_NAMESPACE``
|
||||
``__attribute__((visibility("hidden")))`` inconsistencies are now fixed
|
||||
(affects only unusual environments).
|
||||
`#4043 <https://github.com/pybind/pybind11/pull/4043>`_
|
||||
|
||||
* ``pybind11::detail::get_internals()`` is now resilient to in-flight Python
|
||||
exceptions.
|
||||
`#3981 <https://github.com/pybind/pybind11/pull/3981>`_
|
||||
|
||||
* Arrays with a dimension of size 0 are now properly converted to dynamic Eigen
|
||||
matrices (more common in NumPy 1.23).
|
||||
`#4038 <https://github.com/pybind/pybind11/pull/4038>`_
|
||||
|
||||
* Avoid catching unrelated errors when importing NumPy.
|
||||
`#3974 <https://github.com/pybind/pybind11/pull/3974>`_
|
||||
|
||||
Performance and style:
|
||||
|
||||
* Added an accessor overload of ``(object &&key)`` to reference steal the
|
||||
object when using python types as keys. This prevents unnecessary reference
|
||||
count overhead for attr, dictionary, tuple, and sequence look ups. Added
|
||||
additional regression tests. Fixed a performance bug the caused accessor
|
||||
assignments to potentially perform unnecessary copies.
|
||||
`#3970 <https://github.com/pybind/pybind11/pull/3970>`_
|
||||
|
||||
* Perfect forward all args of ``make_iterator``.
|
||||
`#3980 <https://github.com/pybind/pybind11/pull/3980>`_
|
||||
|
||||
* Avoid potential bug in pycapsule destructor by adding an ``error_guard`` to
|
||||
one of the dtors.
|
||||
`#3958 <https://github.com/pybind/pybind11/pull/3958>`_
|
||||
|
||||
* Optimize dictionary access in ``strip_padding`` for numpy.
|
||||
`#3994 <https://github.com/pybind/pybind11/pull/3994>`_
|
||||
|
||||
* ``stl_bind.h`` bindings now take slice args as a const-ref.
|
||||
`#3852 <https://github.com/pybind/pybind11/pull/3852>`_
|
||||
|
||||
* Made slice constructor more consistent, and improve performance of some
|
||||
casters by allowing reference stealing.
|
||||
`#3845 <https://github.com/pybind/pybind11/pull/3845>`_
|
||||
|
||||
* Change numpy dtype from_args method to use const ref.
|
||||
`#3878 <https://github.com/pybind/pybind11/pull/3878>`_
|
||||
|
||||
* Follow rule of three to ensure ``PyErr_Restore`` is called only once.
|
||||
`#3872 <https://github.com/pybind/pybind11/pull/3872>`_
|
||||
|
||||
* Added missing perfect forwarding for ``make_iterator`` functions.
|
||||
`#3860 <https://github.com/pybind/pybind11/pull/3860>`_
|
||||
|
||||
* Optimize c++ to python function casting by using the rvalue caster.
|
||||
`#3966 <https://github.com/pybind/pybind11/pull/3966>`_
|
||||
|
||||
* Optimize Eigen sparse matrix casting by removing unnecessary temporary.
|
||||
`#4064 <https://github.com/pybind/pybind11/pull/4064>`_
|
||||
|
||||
* Avoid potential implicit copy/assignment constructors causing double free in
|
||||
``strdup_gaurd``.
|
||||
`#3905 <https://github.com/pybind/pybind11/pull/3905>`_
|
||||
|
||||
* Enable clang-tidy checks ``misc-definitions-in-headers``,
|
||||
``modernize-loop-convert``, and ``modernize-use-nullptr``.
|
||||
`#3881 <https://github.com/pybind/pybind11/pull/3881>`_
|
||||
`#3988 <https://github.com/pybind/pybind11/pull/3988>`_
|
||||
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* CMake: Fix file extension on Windows with cp36 and cp37 using FindPython.
|
||||
`#3919 <https://github.com/pybind/pybind11/pull/3919>`_
|
||||
|
||||
* CMake: Support multiple Python targets (such as on vcpkg).
|
||||
`#3948 <https://github.com/pybind/pybind11/pull/3948>`_
|
||||
|
||||
* CMake: Fix issue with NVCC on Windows.
|
||||
`#3947 <https://github.com/pybind/pybind11/pull/3947>`_
|
||||
|
||||
* CMake: Drop the bitness check on cross compiles (like targeting WebAssembly
|
||||
via Emscripten).
|
||||
`#3959 <https://github.com/pybind/pybind11/pull/3959>`_
|
||||
|
||||
* Add MSVC builds in debug mode to CI.
|
||||
`#3784 <https://github.com/pybind/pybind11/pull/3784>`_
|
||||
|
||||
* MSVC 2022 C++20 coverage was added to GitHub Actions, including Eigen.
|
||||
`#3732 <https://github.com/pybind/pybind11/pull/3732>`_,
|
||||
`#3741 <https://github.com/pybind/pybind11/pull/3741>`_
|
||||
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* New theme for the documentation.
|
||||
`#3109 <https://github.com/pybind/pybind11/pull/3109>`_
|
||||
|
||||
* Remove idioms in code comments. Use more inclusive language.
|
||||
`#3809 <https://github.com/pybind/pybind11/pull/3809>`_
|
||||
|
||||
* ``#include <iostream>`` was removed from the ``pybind11/stl.h`` header. Your
|
||||
project may break if it has a transitive dependency on this include. The fix
|
||||
is to "Include What You Use".
|
||||
`#3928 <https://github.com/pybind/pybind11/pull/3928>`_
|
||||
|
||||
* Avoid ``setup.py <command>`` usage in internal tests.
|
||||
`#3734 <https://github.com/pybind/pybind11/pull/3734>`_
|
||||
|
||||
|
||||
Version 2.9.2 (Mar 29, 2022)
|
||||
----------------------------
|
||||
|
||||
Changes:
|
||||
|
||||
* Enum now has an ``__index__`` method on Python <3.8 too.
|
||||
`#3700 <https://github.com/pybind/pybind11/pull/3700>`_
|
||||
|
||||
* Local internals are now cleared after finalizing the interpreter.
|
||||
`#3744 <https://github.com/pybind/pybind11/pull/3744>`_
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Better support for Python 3.11 alphas.
|
||||
`#3694 <https://github.com/pybind/pybind11/pull/3694>`_
|
||||
|
||||
* ``PYBIND11_TYPE_CASTER`` now uses fully qualified symbols, so it can be used
|
||||
outside of ``pybind11::detail``.
|
||||
`#3758 <https://github.com/pybind/pybind11/pull/3758>`_
|
||||
|
||||
* Some fixes for PyPy 3.9.
|
||||
`#3768 <https://github.com/pybind/pybind11/pull/3768>`_
|
||||
|
||||
* Fixed a potential memleak in PyPy in ``get_type_override``.
|
||||
`#3774 <https://github.com/pybind/pybind11/pull/3774>`_
|
||||
|
||||
* Fix usage of ``VISIBILITY_INLINES_HIDDEN``.
|
||||
`#3721 <https://github.com/pybind/pybind11/pull/3721>`_
|
||||
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Uses ``sysconfig`` module to determine installation locations on Python >=
|
||||
3.10, instead of ``distutils`` which has been deprecated.
|
||||
`#3764 <https://github.com/pybind/pybind11/pull/3764>`_
|
||||
|
||||
* Support Catch 2.13.5+ (supporting GLIBC 2.34+).
|
||||
`#3679 <https://github.com/pybind/pybind11/pull/3679>`_
|
||||
|
||||
* Fix test failures with numpy 1.22 by ignoring whitespace when comparing
|
||||
``str()`` of dtypes.
|
||||
`#3682 <https://github.com/pybind/pybind11/pull/3682>`_
|
||||
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* clang-tidy: added ``readability-qualified-auto``,
|
||||
``readability-braces-around-statements``,
|
||||
``cppcoreguidelines-prefer-member-initializer``,
|
||||
``clang-analyzer-optin.performance.Padding``,
|
||||
``cppcoreguidelines-pro-type-static-cast-downcast``, and
|
||||
``readability-inconsistent-declaration-parameter-name``.
|
||||
`#3702 <https://github.com/pybind/pybind11/pull/3702>`_,
|
||||
`#3699 <https://github.com/pybind/pybind11/pull/3699>`_,
|
||||
`#3716 <https://github.com/pybind/pybind11/pull/3716>`_,
|
||||
`#3709 <https://github.com/pybind/pybind11/pull/3709>`_
|
||||
|
||||
* clang-format was added to the pre-commit actions, and the entire code base
|
||||
automatically reformatted (after several iterations preparing for this leap).
|
||||
`#3713 <https://github.com/pybind/pybind11/pull/3713>`_
|
||||
|
||||
|
||||
Version 2.9.1 (Feb 2, 2022)
|
||||
---------------------------
|
||||
|
||||
Changes:
|
||||
|
||||
* If possible, attach Python exception with ``py::raise_from`` to ``TypeError``
|
||||
when casting from C++ to Python. This will give additional info if Python
|
||||
exceptions occur in the caster. Adds a test case of trying to convert a set
|
||||
from C++ to Python when the hash function is not defined in Python.
|
||||
`#3605 <https://github.com/pybind/pybind11/pull/3605>`_
|
||||
|
||||
* Add a mapping of C++11 nested exceptions to their Python exception
|
||||
equivalent using ``py::raise_from``. This attaches the nested exceptions in
|
||||
Python using the ``__cause__`` field.
|
||||
`#3608 <https://github.com/pybind/pybind11/pull/3608>`_
|
||||
|
||||
* Propagate Python exception traceback using ``raise_from`` if a pybind11
|
||||
function runs out of overloads.
|
||||
`#3671 <https://github.com/pybind/pybind11/pull/3671>`_
|
||||
|
||||
* ``py::multiple_inheritance`` is now only needed when C++ bases are hidden
|
||||
from pybind11.
|
||||
`#3650 <https://github.com/pybind/pybind11/pull/3650>`_ and
|
||||
`#3659 <https://github.com/pybind/pybind11/pull/3659>`_
|
||||
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Remove a boolean cast in ``numpy.h`` that causes MSVC C4800 warnings when
|
||||
compiling against Python 3.10 or newer.
|
||||
`#3669 <https://github.com/pybind/pybind11/pull/3669>`_
|
||||
|
||||
* Render ``py::bool_`` and ``py::float_`` as ``bool`` and ``float``
|
||||
respectively.
|
||||
`#3622 <https://github.com/pybind/pybind11/pull/3622>`_
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Fix CMake extension suffix computation on Python 3.10+.
|
||||
`#3663 <https://github.com/pybind/pybind11/pull/3663>`_
|
||||
|
||||
* Allow ``CMAKE_ARGS`` to override CMake args in pybind11's own ``setup.py``.
|
||||
`#3577 <https://github.com/pybind/pybind11/pull/3577>`_
|
||||
|
||||
* Remove a few deprecated c-headers.
|
||||
`#3610 <https://github.com/pybind/pybind11/pull/3610>`_
|
||||
|
||||
* More uniform handling of test targets.
|
||||
`#3590 <https://github.com/pybind/pybind11/pull/3590>`_
|
||||
|
||||
* Add clang-tidy readability check to catch potentially swapped function args.
|
||||
`#3611 <https://github.com/pybind/pybind11/pull/3611>`_
|
||||
|
||||
|
||||
Version 2.9.0 (Dec 28, 2021)
|
||||
----------------------------
|
||||
|
||||
This is the last version to support Python 2.7 and 3.5.
|
||||
|
||||
New Features:
|
||||
|
||||
* Allow ``py::args`` to be followed by other arguments; the remaining arguments
|
||||
are implicitly keyword-only, as if a ``py::kw_only{}`` annotation had been
|
||||
used.
|
||||
`#3402 <https://github.com/pybind/pybind11/pull/3402>`_
|
||||
|
||||
Changes:
|
||||
|
||||
* Make str/bytes/memoryview more interoperable with ``std::string_view``.
|
||||
`#3521 <https://github.com/pybind/pybind11/pull/3521>`_
|
||||
|
||||
* Replace ``_`` with ``const_name`` in internals, avoid defining ``pybind::_``
|
||||
if ``_`` defined as macro (common gettext usage)
|
||||
`#3423 <https://github.com/pybind/pybind11/pull/3423>`_
|
||||
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix a rare warning about extra copy in an Eigen constructor.
|
||||
`#3486 <https://github.com/pybind/pybind11/pull/3486>`_
|
||||
|
||||
* Fix caching of the C++ overrides.
|
||||
`#3465 <https://github.com/pybind/pybind11/pull/3465>`_
|
||||
|
||||
* Add missing ``std::forward`` calls to some ``cpp_function`` overloads.
|
||||
`#3443 <https://github.com/pybind/pybind11/pull/3443>`_
|
||||
|
||||
* Support PyPy 7.3.7 and the PyPy3.8 beta. Test python-3.11 on PRs with the
|
||||
``python dev`` label.
|
||||
`#3419 <https://github.com/pybind/pybind11/pull/3419>`_
|
||||
|
||||
* Replace usage of deprecated ``Eigen::MappedSparseMatrix`` with
|
||||
``Eigen::Map<Eigen::SparseMatrix<...>>`` for Eigen 3.3+.
|
||||
`#3499 <https://github.com/pybind/pybind11/pull/3499>`_
|
||||
|
||||
* Tweaks to support Microsoft Visual Studio 2022.
|
||||
`#3497 <https://github.com/pybind/pybind11/pull/3497>`_
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Nicer CMake printout and IDE organisation for pybind11's own tests.
|
||||
`#3479 <https://github.com/pybind/pybind11/pull/3479>`_
|
||||
|
||||
* CMake: report version type as part of the version string to avoid a spurious
|
||||
space in the package status message.
|
||||
`#3472 <https://github.com/pybind/pybind11/pull/3472>`_
|
||||
|
||||
* Flags starting with ``-g`` in ``$CFLAGS`` and ``$CPPFLAGS`` are no longer
|
||||
overridden by ``.Pybind11Extension``.
|
||||
`#3436 <https://github.com/pybind/pybind11/pull/3436>`_
|
||||
|
||||
* Ensure ThreadPool is closed in ``setup_helpers``.
|
||||
`#3548 <https://github.com/pybind/pybind11/pull/3548>`_
|
||||
|
||||
* Avoid LTS on ``mips64`` and ``ppc64le`` (reported broken).
|
||||
`#3557 <https://github.com/pybind/pybind11/pull/3557>`_
|
||||
|
||||
|
||||
v2.8.1 (Oct 27, 2021)
|
||||
---------------------
|
||||
|
||||
Changes and additions:
|
||||
|
||||
* The simple namespace creation shortcut added in 2.8.0 was deprecated due to
|
||||
usage of CPython internal API, and will be removed soon. Use
|
||||
``py::module_::import("types").attr("SimpleNamespace")``.
|
||||
`#3374 <https://github.com/pybinyyd/pybind11/pull/3374>`_
|
||||
|
||||
* Add C++ Exception type to throw and catch ``AttributeError``. Useful for
|
||||
defining custom ``__setattr__`` and ``__getattr__`` methods.
|
||||
`#3387 <https://github.com/pybind/pybind11/pull/3387>`_
|
||||
|
||||
Fixes:
|
||||
|
||||
* Fixed the potential for dangling references when using properties with
|
||||
``std::optional`` types.
|
||||
`#3376 <https://github.com/pybind/pybind11/pull/3376>`_
|
||||
|
||||
* Modernize usage of ``PyCodeObject`` on Python 3.9+ (moving toward support for
|
||||
Python 3.11a1)
|
||||
`#3368 <https://github.com/pybind/pybind11/pull/3368>`_
|
||||
|
||||
* A long-standing bug in ``eigen.h`` was fixed (originally PR #3343). The bug
|
||||
was unmasked by newly added ``static_assert``'s in the Eigen 3.4.0 release.
|
||||
`#3352 <https://github.com/pybind/pybind11/pull/3352>`_
|
||||
|
||||
* Support multiple raw inclusion of CMake helper files (Conan.io does this for
|
||||
multi-config generators).
|
||||
`#3420 <https://github.com/pybind/pybind11/pull/3420>`_
|
||||
|
||||
* Fix harmless warning on upcoming CMake 3.22.
|
||||
`#3368 <https://github.com/pybind/pybind11/pull/3368>`_
|
||||
|
||||
* Fix 2.8.0 regression with MSVC 2017 + C++17 mode + Python 3.
|
||||
`#3407 <https://github.com/pybind/pybind11/pull/3407>`_
|
||||
|
||||
* Fix 2.8.0 regression that caused undefined behavior (typically
|
||||
segfaults) in ``make_key_iterator``/``make_value_iterator`` if dereferencing
|
||||
the iterator returned a temporary value instead of a reference.
|
||||
`#3348 <https://github.com/pybind/pybind11/pull/3348>`_
|
||||
|
||||
|
||||
v2.8.0 (Oct 4, 2021)
|
||||
--------------------
|
||||
|
||||
New features:
|
||||
|
||||
* Added ``py::raise_from`` to enable chaining exceptions.
|
||||
`#3215 <https://github.com/pybind/pybind11/pull/3215>`_
|
||||
|
||||
* Allow exception translators to be optionally registered local to a module
|
||||
instead of applying globally across all pybind11 modules. Use
|
||||
``register_local_exception_translator(ExceptionTranslator&& translator)``
|
||||
instead of ``register_exception_translator(ExceptionTranslator&&
|
||||
translator)`` to keep your exception remapping code local to the module.
|
||||
`#2650 <https://github.com/pybinyyd/pybind11/pull/2650>`_
|
||||
|
||||
* Add ``make_simple_namespace`` function for instantiating Python
|
||||
``SimpleNamespace`` objects. **Deprecated in 2.8.1.**
|
||||
`#2840 <https://github.com/pybind/pybind11/pull/2840>`_
|
||||
|
||||
* ``pybind11::scoped_interpreter`` and ``initialize_interpreter`` have new
|
||||
arguments to allow ``sys.argv`` initialization.
|
||||
`#2341 <https://github.com/pybind/pybind11/pull/2341>`_
|
||||
|
||||
* Allow Python builtins to be used as callbacks in CPython.
|
||||
`#1413 <https://github.com/pybind/pybind11/pull/1413>`_
|
||||
|
||||
* Added ``view`` to view arrays with a different datatype.
|
||||
`#987 <https://github.com/pybind/pybind11/pull/987>`_
|
||||
|
||||
* Implemented ``reshape`` on arrays.
|
||||
`#984 <https://github.com/pybind/pybind11/pull/984>`_
|
||||
|
||||
* Enable defining custom ``__new__`` methods on classes by fixing bug
|
||||
preventing overriding methods if they have non-pybind11 siblings.
|
||||
`#3265 <https://github.com/pybind/pybind11/pull/3265>`_
|
||||
|
||||
* Add ``make_value_iterator()``, and fix ``make_key_iterator()`` to return
|
||||
references instead of copies.
|
||||
`#3293 <https://github.com/pybind/pybind11/pull/3293>`_
|
||||
|
||||
* Improve the classes generated by ``bind_map``: `#3310 <https://github.com/pybind/pybind11/pull/3310>`_
|
||||
|
||||
* Change ``.items`` from an iterator to a dictionary view.
|
||||
* Add ``.keys`` and ``.values`` (both dictionary views).
|
||||
* Allow ``__contains__`` to take any object.
|
||||
|
||||
* ``pybind11::custom_type_setup`` was added, for customizing the
|
||||
``PyHeapTypeObject`` corresponding to a class, which may be useful for
|
||||
enabling garbage collection support, among other things.
|
||||
`#3287 <https://github.com/pybind/pybind11/pull/3287>`_
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
* Set ``__file__`` constant when running ``eval_file`` in an embedded interpreter.
|
||||
`#3233 <https://github.com/pybind/pybind11/pull/3233>`_
|
||||
|
||||
* Python objects and (C++17) ``std::optional`` now accepted in ``py::slice``
|
||||
constructor.
|
||||
`#1101 <https://github.com/pybind/pybind11/pull/1101>`_
|
||||
|
||||
* The pybind11 proxy types ``str``, ``bytes``, ``bytearray``, ``tuple``,
|
||||
``list`` now consistently support passing ``ssize_t`` values for sizes and
|
||||
indexes. Previously, only ``size_t`` was accepted in several interfaces.
|
||||
`#3219 <https://github.com/pybind/pybind11/pull/3219>`_
|
||||
|
||||
* Avoid evaluating ``PYBIND11_TLS_REPLACE_VALUE`` arguments more than once.
|
||||
`#3290 <https://github.com/pybind/pybind11/pull/3290>`_
|
||||
|
||||
Fixes:
|
||||
|
||||
* Bug fix: enum value's ``__int__`` returning non-int when underlying type is
|
||||
bool or of char type.
|
||||
`#1334 <https://github.com/pybind/pybind11/pull/1334>`_
|
||||
|
||||
* Fixes bug in setting error state in Capsule's pointer methods.
|
||||
`#3261 <https://github.com/pybind/pybind11/pull/3261>`_
|
||||
|
||||
* A long-standing memory leak in ``py::cpp_function::initialize`` was fixed.
|
||||
`#3229 <https://github.com/pybind/pybind11/pull/3229>`_
|
||||
|
||||
* Fixes thread safety for some ``pybind11::type_caster`` which require lifetime
|
||||
extension, such as for ``std::string_view``.
|
||||
`#3237 <https://github.com/pybind/pybind11/pull/3237>`_
|
||||
|
||||
* Restore compatibility with gcc 4.8.4 as distributed by ubuntu-trusty, linuxmint-17.
|
||||
`#3270 <https://github.com/pybind/pybind11/pull/3270>`_
|
||||
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* Fix regression in CMake Python package config: improper use of absolute path.
|
||||
`#3144 <https://github.com/pybind/pybind11/pull/3144>`_
|
||||
|
||||
* Cached Python version information could become stale when CMake was re-run
|
||||
with a different Python version. The build system now detects this and
|
||||
updates this information.
|
||||
`#3299 <https://github.com/pybind/pybind11/pull/3299>`_
|
||||
|
||||
* Specified UTF8-encoding in setup.py calls of open().
|
||||
`#3137 <https://github.com/pybind/pybind11/pull/3137>`_
|
||||
|
||||
* Fix a harmless warning from CMake 3.21 with the classic Python discovery.
|
||||
`#3220 <https://github.com/pybind/pybind11/pull/3220>`_
|
||||
|
||||
* Eigen repo and version can now be specified as cmake options.
|
||||
`#3324 <https://github.com/pybind/pybind11/pull/3324>`_
|
||||
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* Reduced thread-local storage required for keeping alive temporary data for
|
||||
type conversion to one key per ABI version, rather than one key per extension
|
||||
module. This makes the total thread-local storage required by pybind11 2
|
||||
keys per ABI version.
|
||||
`#3275 <https://github.com/pybind/pybind11/pull/3275>`_
|
||||
|
||||
* Optimize NumPy array construction with additional moves.
|
||||
`#3183 <https://github.com/pybind/pybind11/pull/3183>`_
|
||||
|
||||
* Conversion to ``std::string`` and ``std::string_view`` now avoids making an
|
||||
extra copy of the data on Python >= 3.3.
|
||||
`#3257 <https://github.com/pybind/pybind11/pull/3257>`_
|
||||
|
||||
* Remove const modifier from certain C++ methods on Python collections
|
||||
(``list``, ``set``, ``dict``) such as (``clear()``, ``append()``,
|
||||
``insert()``, etc...) and annotated them with ``py-non-const``.
|
||||
|
||||
* Enable readability ``clang-tidy-const-return`` and remove useless consts.
|
||||
`#3254 <https://github.com/pybind/pybind11/pull/3254>`_
|
||||
`#3194 <https://github.com/pybind/pybind11/pull/3194>`_
|
||||
|
||||
* The clang-tidy ``google-explicit-constructor`` option was enabled.
|
||||
`#3250 <https://github.com/pybind/pybind11/pull/3250>`_
|
||||
|
||||
* Mark a pytype move constructor as noexcept (perf).
|
||||
`#3236 <https://github.com/pybind/pybind11/pull/3236>`_
|
||||
|
||||
* Enable clang-tidy check to guard against inheritance slicing.
|
||||
`#3210 <https://github.com/pybind/pybind11/pull/3210>`_
|
||||
|
||||
* Legacy warning suppression pragma were removed from eigen.h. On Unix
|
||||
platforms, please use -isystem for Eigen include directories, to suppress
|
||||
compiler warnings originating from Eigen headers. Note that CMake does this
|
||||
by default. No adjustments are needed for Windows.
|
||||
`#3198 <https://github.com/pybind/pybind11/pull/3198>`_
|
||||
|
||||
* Format pybind11 with isort consistent ordering of imports
|
||||
`#3195 <https://github.com/pybind/pybind11/pull/3195>`_
|
||||
|
||||
* The warnings-suppression "pragma clamp" at the top/bottom of pybind11 was
|
||||
removed, clearing the path to refactoring and IWYU cleanup.
|
||||
`#3186 <https://github.com/pybind/pybind11/pull/3186>`_
|
||||
|
||||
* Enable most bugprone checks in clang-tidy and fix the found potential bugs
|
||||
and poor coding styles.
|
||||
`#3166 <https://github.com/pybind/pybind11/pull/3166>`_
|
||||
|
||||
* Add ``clang-tidy-readability`` rules to make boolean casts explicit improving
|
||||
code readability. Also enabled other misc and readability clang-tidy checks.
|
||||
`#3148 <https://github.com/pybind/pybind11/pull/3148>`_
|
||||
|
||||
* Move object in ``.pop()`` for list.
|
||||
`#3116 <https://github.com/pybind/pybind11/pull/3116>`_
|
||||
|
||||
|
||||
|
||||
|
||||
v2.7.1 (Aug 3, 2021)
|
||||
---------------------
|
||||
|
||||
Minor missing functionality added:
|
||||
|
||||
* Allow Python builtins to be used as callbacks in CPython.
|
||||
`#1413 <https://github.com/pybind/pybind11/pull/1413>`_
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fix regression in CMake Python package config: improper use of absolute path.
|
||||
`#3144 <https://github.com/pybind/pybind11/pull/3144>`_
|
||||
|
||||
* Fix Mingw64 and add to the CI testing matrix.
|
||||
`#3132 <https://github.com/pybind/pybind11/pull/3132>`_
|
||||
|
||||
* Specified UTF8-encoding in setup.py calls of open().
|
||||
`#3137 <https://github.com/pybind/pybind11/pull/3137>`_
|
||||
|
||||
* Add clang-tidy-readability rules to make boolean casts explicit improving
|
||||
code readability. Also enabled other misc and readability clang-tidy checks.
|
||||
`#3148 <https://github.com/pybind/pybind11/pull/3148>`_
|
||||
|
||||
* Move object in ``.pop()`` for list.
|
||||
`#3116 <https://github.com/pybind/pybind11/pull/3116>`_
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* Removed and fixed warning suppressions.
|
||||
`#3127 <https://github.com/pybind/pybind11/pull/3127>`_
|
||||
`#3129 <https://github.com/pybind/pybind11/pull/3129>`_
|
||||
`#3135 <https://github.com/pybind/pybind11/pull/3135>`_
|
||||
`#3141 <https://github.com/pybind/pybind11/pull/3141>`_
|
||||
`#3142 <https://github.com/pybind/pybind11/pull/3142>`_
|
||||
`#3150 <https://github.com/pybind/pybind11/pull/3150>`_
|
||||
`#3152 <https://github.com/pybind/pybind11/pull/3152>`_
|
||||
`#3160 <https://github.com/pybind/pybind11/pull/3160>`_
|
||||
`#3161 <https://github.com/pybind/pybind11/pull/3161>`_
|
||||
|
||||
|
||||
v2.7.0 (Jul 16, 2021)
|
||||
---------------------
|
||||
|
||||
New features:
|
||||
|
||||
* Enable ``py::implicitly_convertible<py::none, ...>`` for
|
||||
``py::class_``-wrapped types.
|
||||
`#3059 <https://github.com/pybind/pybind11/pull/3059>`_
|
||||
|
||||
* Allow function pointer extraction from overloaded functions.
|
||||
`#2944 <https://github.com/pybind/pybind11/pull/2944>`_
|
||||
|
||||
* NumPy: added ``.char_()`` to type which gives the NumPy public ``char``
|
||||
result, which also distinguishes types by bit length (unlike ``.kind()``).
|
||||
`#2864 <https://github.com/pybind/pybind11/pull/2864>`_
|
||||
|
||||
* Add ``pybind11::bytearray`` to manipulate ``bytearray`` similar to ``bytes``.
|
||||
`#2799 <https://github.com/pybind/pybind11/pull/2799>`_
|
||||
|
||||
* ``pybind11/stl/filesystem.h`` registers a type caster that, on C++17/Python
|
||||
3.6+, converts ``std::filesystem::path`` to ``pathlib.Path`` and any
|
||||
``os.PathLike`` to ``std::filesystem::path``.
|
||||
`#2730 <https://github.com/pybind/pybind11/pull/2730>`_
|
||||
|
||||
* A ``PYBIND11_VERSION_HEX`` define was added, similar to ``PY_VERSION_HEX``.
|
||||
`#3120 <https://github.com/pybind/pybind11/pull/3120>`_
|
||||
|
||||
|
||||
|
||||
Changes:
|
||||
|
||||
* ``py::str`` changed to exclusively hold ``PyUnicodeObject``. Previously
|
||||
``py::str`` could also hold ``bytes``, which is probably surprising, was
|
||||
never documented, and can mask bugs (e.g. accidental use of ``py::str``
|
||||
instead of ``py::bytes``).
|
||||
`#2409 <https://github.com/pybind/pybind11/pull/2409>`_
|
||||
|
||||
* Add a safety guard to ensure that the Python GIL is held when C++ calls back
|
||||
into Python via ``object_api<>::operator()`` (e.g. ``py::function``
|
||||
``__call__``). (This feature is available for Python 3.6+ only.)
|
||||
`#2919 <https://github.com/pybind/pybind11/pull/2919>`_
|
||||
|
||||
* Catch a missing ``self`` argument in calls to ``__init__()``.
|
||||
`#2914 <https://github.com/pybind/pybind11/pull/2914>`_
|
||||
|
||||
* Use ``std::string_view`` if available to avoid a copy when passing an object
|
||||
to a ``std::ostream``.
|
||||
`#3042 <https://github.com/pybind/pybind11/pull/3042>`_
|
||||
|
||||
* An important warning about thread safety was added to the ``iostream.h``
|
||||
documentation; attempts to make ``py::scoped_ostream_redirect`` thread safe
|
||||
have been removed, as it was only partially effective.
|
||||
`#2995 <https://github.com/pybind/pybind11/pull/2995>`_
|
||||
|
||||
|
||||
Fixes:
|
||||
|
||||
* Performance: avoid unnecessary strlen calls.
|
||||
`#3058 <https://github.com/pybind/pybind11/pull/3058>`_
|
||||
|
||||
* Fix auto-generated documentation string when using ``const T`` in
|
||||
``pyarray_t``.
|
||||
`#3020 <https://github.com/pybind/pybind11/pull/3020>`_
|
||||
|
||||
* Unify error messages thrown by ``simple_collector``/``unpacking_collector``.
|
||||
`#3013 <https://github.com/pybind/pybind11/pull/3013>`_
|
||||
|
||||
* ``pybind11::builtin_exception`` is now explicitly exported, which means the
|
||||
types included/defined in different modules are identical, and exceptions
|
||||
raised in different modules can be caught correctly. The documentation was
|
||||
updated to explain that custom exceptions that are used across module
|
||||
boundaries need to be explicitly exported as well.
|
||||
`#2999 <https://github.com/pybind/pybind11/pull/2999>`_
|
||||
|
||||
* Fixed exception when printing UTF-8 to a ``scoped_ostream_redirect``.
|
||||
`#2982 <https://github.com/pybind/pybind11/pull/2982>`_
|
||||
|
||||
* Pickle support enhancement: ``setstate`` implementation will attempt to
|
||||
``setattr`` ``__dict__`` only if the unpickled ``dict`` object is not empty,
|
||||
to not force use of ``py::dynamic_attr()`` unnecessarily.
|
||||
`#2972 <https://github.com/pybind/pybind11/pull/2972>`_
|
||||
|
||||
* Allow negative timedelta values to roundtrip.
|
||||
`#2870 <https://github.com/pybind/pybind11/pull/2870>`_
|
||||
|
||||
* Fix unchecked errors could potentially swallow signals/other exceptions.
|
||||
`#2863 <https://github.com/pybind/pybind11/pull/2863>`_
|
||||
|
||||
* Add null pointer check with ``std::localtime``.
|
||||
`#2846 <https://github.com/pybind/pybind11/pull/2846>`_
|
||||
|
||||
* Fix the ``weakref`` constructor from ``py::object`` to create a new
|
||||
``weakref`` on conversion.
|
||||
`#2832 <https://github.com/pybind/pybind11/pull/2832>`_
|
||||
|
||||
* Avoid relying on exceptions in C++17 when getting a ``shared_ptr`` holder
|
||||
from a ``shared_from_this`` class.
|
||||
`#2819 <https://github.com/pybind/pybind11/pull/2819>`_
|
||||
|
||||
* Allow the codec's exception to be raised instead of :code:`RuntimeError` when
|
||||
casting from :code:`py::str` to :code:`std::string`.
|
||||
`#2903 <https://github.com/pybind/pybind11/pull/2903>`_
|
||||
|
||||
|
||||
Build system improvements:
|
||||
|
||||
* In ``setup_helpers.py``, test for platforms that have some multiprocessing
|
||||
features but lack semaphores, which ``ParallelCompile`` requires.
|
||||
`#3043 <https://github.com/pybind/pybind11/pull/3043>`_
|
||||
|
||||
* Fix ``pybind11_INCLUDE_DIR`` in case ``CMAKE_INSTALL_INCLUDEDIR`` is
|
||||
absolute.
|
||||
`#3005 <https://github.com/pybind/pybind11/pull/3005>`_
|
||||
|
||||
* Fix bug not respecting ``WITH_SOABI`` or ``WITHOUT_SOABI`` to CMake.
|
||||
`#2938 <https://github.com/pybind/pybind11/pull/2938>`_
|
||||
|
||||
* Fix the default ``Pybind11Extension`` compilation flags with a Mingw64 python.
|
||||
`#2921 <https://github.com/pybind/pybind11/pull/2921>`_
|
||||
|
||||
* Clang on Windows: do not pass ``/MP`` (ignored flag).
|
||||
`#2824 <https://github.com/pybind/pybind11/pull/2824>`_
|
||||
|
||||
* ``pybind11.setup_helpers.intree_extensions`` can be used to generate
|
||||
``Pybind11Extension`` instances from cpp files placed in the Python package
|
||||
source tree.
|
||||
`#2831 <https://github.com/pybind/pybind11/pull/2831>`_
|
||||
|
||||
Backend and tidying up:
|
||||
|
||||
* Enable clang-tidy performance, readability, and modernization checks
|
||||
throughout the codebase to enforce best coding practices.
|
||||
`#3046 <https://github.com/pybind/pybind11/pull/3046>`_,
|
||||
`#3049 <https://github.com/pybind/pybind11/pull/3049>`_,
|
||||
`#3051 <https://github.com/pybind/pybind11/pull/3051>`_,
|
||||
`#3052 <https://github.com/pybind/pybind11/pull/3052>`_,
|
||||
`#3080 <https://github.com/pybind/pybind11/pull/3080>`_, and
|
||||
`#3094 <https://github.com/pybind/pybind11/pull/3094>`_
|
||||
|
||||
|
||||
* Checks for common misspellings were added to the pre-commit hooks.
|
||||
`#3076 <https://github.com/pybind/pybind11/pull/3076>`_
|
||||
|
||||
* Changed ``Werror`` to stricter ``Werror-all`` for Intel compiler and fixed
|
||||
minor issues.
|
||||
`#2948 <https://github.com/pybind/pybind11/pull/2948>`_
|
||||
|
||||
* Fixed compilation with GCC < 5 when the user defines ``_GLIBCXX_USE_CXX11_ABI``.
|
||||
`#2956 <https://github.com/pybind/pybind11/pull/2956>`_
|
||||
|
||||
* Added nox support for easier local testing and linting of contributions.
|
||||
`#3101 <https://github.com/pybind/pybind11/pull/3101>`_ and
|
||||
`#3121 <https://github.com/pybind/pybind11/pull/3121>`_
|
||||
|
||||
* Avoid RTD style issue with docutils 0.17+.
|
||||
`#3119 <https://github.com/pybind/pybind11/pull/3119>`_
|
||||
|
||||
* Support pipx run, such as ``pipx run pybind11 --include`` for a quick compile.
|
||||
`#3117 <https://github.com/pybind/pybind11/pull/3117>`_
|
||||
|
||||
|
||||
|
||||
v2.6.2 (Jan 26, 2021)
|
||||
---------------------
|
||||
|
||||
Minor missing functionality added:
|
||||
|
||||
* enum: add missing Enum.value property.
|
||||
`#2739 <https://github.com/pybind/pybind11/pull/2739>`_
|
||||
|
||||
* Allow thread termination to be avoided during shutdown for CPython 3.7+ via
|
||||
``.disarm`` for ``gil_scoped_acquire``/``gil_scoped_release``.
|
||||
`#2657 <https://github.com/pybind/pybind11/pull/2657>`_
|
||||
|
||||
Fixed or improved behavior in a few special cases:
|
||||
|
||||
* Fix bug where the constructor of ``object`` subclasses would not throw on
|
||||
being passed a Python object of the wrong type.
|
||||
`#2701 <https://github.com/pybind/pybind11/pull/2701>`_
|
||||
|
||||
* The ``type_caster`` for integers does not convert Python objects with
|
||||
``__int__`` anymore with ``noconvert`` or during the first round of trying
|
||||
overloads.
|
||||
`#2698 <https://github.com/pybind/pybind11/pull/2698>`_
|
||||
|
||||
* When casting to a C++ integer, ``__index__`` is always called and not
|
||||
considered as conversion, consistent with Python 3.8+.
|
||||
`#2801 <https://github.com/pybind/pybind11/pull/2801>`_
|
||||
|
||||
Build improvements:
|
||||
|
||||
* Setup helpers: ``extra_compile_args`` and ``extra_link_args`` automatically set by
|
||||
Pybind11Extension are now prepended, which allows them to be overridden
|
||||
by user-set ``extra_compile_args`` and ``extra_link_args``.
|
||||
`#2808 <https://github.com/pybind/pybind11/pull/2808>`_
|
||||
|
||||
* Setup helpers: Don't trigger unused parameter warning.
|
||||
`#2735 <https://github.com/pybind/pybind11/pull/2735>`_
|
||||
|
||||
* CMake: Support running with ``--warn-uninitialized`` active.
|
||||
`#2806 <https://github.com/pybind/pybind11/pull/2806>`_
|
||||
|
||||
* CMake: Avoid error if included from two submodule directories.
|
||||
`#2804 <https://github.com/pybind/pybind11/pull/2804>`_
|
||||
|
||||
* CMake: Fix ``STATIC`` / ``SHARED`` being ignored in FindPython mode.
|
||||
`#2796 <https://github.com/pybind/pybind11/pull/2796>`_
|
||||
|
||||
* CMake: Respect the setting for ``CMAKE_CXX_VISIBILITY_PRESET`` if defined.
|
||||
`#2793 <https://github.com/pybind/pybind11/pull/2793>`_
|
||||
|
||||
* CMake: Fix issue with FindPython2/FindPython3 not working with ``pybind11::embed``.
|
||||
`#2662 <https://github.com/pybind/pybind11/pull/2662>`_
|
||||
|
||||
* CMake: mixing local and installed pybind11's would prioritize the installed
|
||||
one over the local one (regression in 2.6.0).
|
||||
`#2716 <https://github.com/pybind/pybind11/pull/2716>`_
|
||||
|
||||
|
||||
Bug fixes:
|
||||
|
||||
* Fixed segfault in multithreaded environments when using
|
||||
``scoped_ostream_redirect``.
|
||||
`#2675 <https://github.com/pybind/pybind11/pull/2675>`_
|
||||
|
||||
* Leave docstring unset when all docstring-related options are disabled, rather
|
||||
than set an empty string.
|
||||
`#2745 <https://github.com/pybind/pybind11/pull/2745>`_
|
||||
|
||||
* The module key in builtins that pybind11 uses to store its internals changed
|
||||
from std::string to a python str type (more natural on Python 2, no change on
|
||||
Python 3).
|
||||
`#2814 <https://github.com/pybind/pybind11/pull/2814>`_
|
||||
|
||||
* Fixed assertion error related to unhandled (later overwritten) exception in
|
||||
CPython 3.8 and 3.9 debug builds.
|
||||
`#2685 <https://github.com/pybind/pybind11/pull/2685>`_
|
||||
|
||||
* Fix ``py::gil_scoped_acquire`` assert with CPython 3.9 debug build.
|
||||
`#2683 <https://github.com/pybind/pybind11/pull/2683>`_
|
||||
|
||||
* Fix issue with a test failing on pytest 6.2.
|
||||
`#2741 <https://github.com/pybind/pybind11/pull/2741>`_
|
||||
|
||||
Warning fixes:
|
||||
|
||||
* Fix warning modifying constructor parameter 'flag' that shadows a field of
|
||||
'set_flag' ``[-Wshadow-field-in-constructor-modified]``.
|
||||
`#2780 <https://github.com/pybind/pybind11/pull/2780>`_
|
||||
|
||||
* Suppressed some deprecation warnings about old-style
|
||||
``__init__``/``__setstate__`` in the tests.
|
||||
`#2759 <https://github.com/pybind/pybind11/pull/2759>`_
|
||||
|
||||
Valgrind work:
|
||||
|
||||
* Fix invalid access when calling a pybind11 ``__init__`` on a non-pybind11
|
||||
class instance.
|
||||
`#2755 <https://github.com/pybind/pybind11/pull/2755>`_
|
||||
|
||||
* Fixed various minor memory leaks in pybind11's test suite.
|
||||
`#2758 <https://github.com/pybind/pybind11/pull/2758>`_
|
||||
|
||||
* Resolved memory leak in cpp_function initialization when exceptions occurred.
|
||||
`#2756 <https://github.com/pybind/pybind11/pull/2756>`_
|
||||
|
||||
* Added a Valgrind build, checking for leaks and memory-related UB, to CI.
|
||||
`#2746 <https://github.com/pybind/pybind11/pull/2746>`_
|
||||
|
||||
Compiler support:
|
||||
|
||||
* Intel compiler was not activating C++14 support due to a broken define.
|
||||
`#2679 <https://github.com/pybind/pybind11/pull/2679>`_
|
||||
|
||||
* Support ICC and NVIDIA HPC SDK in C++17 mode.
|
||||
`#2729 <https://github.com/pybind/pybind11/pull/2729>`_
|
||||
|
||||
* Support Intel OneAPI compiler (ICC 20.2) and add to CI.
|
||||
`#2573 <https://github.com/pybind/pybind11/pull/2573>`_
|
||||
|
||||
|
||||
|
||||
v2.6.1 (Nov 11, 2020)
|
||||
---------------------
|
||||
|
||||
@ -14,7 +939,7 @@ v2.6.1 (Nov 11, 2020)
|
||||
and ``eval`` in pure Python.
|
||||
`#2616 <https://github.com/pybind/pybind11/pull/2616>`_
|
||||
|
||||
* ``setup_helpers`` will no longer set a minimum macOS version lower than the
|
||||
* ``setup_helpers`` will no longer set a minimum macOS version higher than the
|
||||
current version.
|
||||
`#2622 <https://github.com/pybind/pybind11/pull/2622>`_
|
||||
|
||||
@ -142,7 +1067,7 @@ Packaging / building improvements:
|
||||
`#2338 <https://github.com/pybind/pybind11/pull/2338>`_ and
|
||||
`#2370 <https://github.com/pybind/pybind11/pull/2370>`_
|
||||
|
||||
* Full integration with CMake’s C++ standard system and compile features
|
||||
* Full integration with CMake's C++ standard system and compile features
|
||||
replaces ``PYBIND11_CPP_STANDARD``.
|
||||
|
||||
* Generated config file is now portable to different Python/compiler/CMake
|
||||
@ -374,7 +1299,7 @@ v2.4.0 (Sep 19, 2019)
|
||||
`#1888 <https://github.com/pybind/pybind11/pull/1888>`_.
|
||||
|
||||
* ``py::details::overload_cast_impl`` is available in C++11 mode, can be used
|
||||
like ``overload_cast`` with an additional set of parantheses.
|
||||
like ``overload_cast`` with an additional set of parentheses.
|
||||
`#1581 <https://github.com/pybind/pybind11/pull/1581>`_.
|
||||
|
||||
* Fixed ``get_include()`` on Conda.
|
||||
@ -696,6 +1621,7 @@ v2.2.0 (August 31, 2017)
|
||||
|
||||
from cpp_module import CppBase1, CppBase2
|
||||
|
||||
|
||||
class PyDerived(CppBase1, CppBase2):
|
||||
def __init__(self):
|
||||
CppBase1.__init__(self) # C++ bases must be initialized explicitly
|
||||
@ -908,7 +1834,7 @@ v2.2.0 (August 31, 2017)
|
||||
* Intel C++ compiler compatibility fixes.
|
||||
`#937 <https://github.com/pybind/pybind11/pull/937>`_.
|
||||
|
||||
* Fixed implicit conversion of `py::enum_` to integer types on Python 2.7.
|
||||
* Fixed implicit conversion of ``py::enum_`` to integer types on Python 2.7.
|
||||
`#821 <https://github.com/pybind/pybind11/pull/821>`_.
|
||||
|
||||
* Added ``py::hash`` to fetch the hash value of Python objects, and
|
||||
|
59
3rdparty/pybind11/docs/classes.rst
vendored
59
3rdparty/pybind11/docs/classes.rst
vendored
@ -44,14 +44,14 @@ interactive Python session demonstrating this example is shown below:
|
||||
|
||||
% python
|
||||
>>> import example
|
||||
>>> p = example.Pet('Molly')
|
||||
>>> p = example.Pet("Molly")
|
||||
>>> print(p)
|
||||
<example.Pet object at 0x10cd98060>
|
||||
>>> p.getName()
|
||||
u'Molly'
|
||||
>>> p.setName('Charly')
|
||||
'Molly'
|
||||
>>> p.setName("Charly")
|
||||
>>> p.getName()
|
||||
u'Charly'
|
||||
'Charly'
|
||||
|
||||
.. seealso::
|
||||
|
||||
@ -122,12 +122,12 @@ This makes it possible to write
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = example.Pet('Molly')
|
||||
>>> p = example.Pet("Molly")
|
||||
>>> p.name
|
||||
u'Molly'
|
||||
>>> p.name = 'Charly'
|
||||
'Molly'
|
||||
>>> p.name = "Charly"
|
||||
>>> p.name
|
||||
u'Charly'
|
||||
'Charly'
|
||||
|
||||
Now suppose that ``Pet::name`` was a private internal variable
|
||||
that can only be accessed via setters and getters.
|
||||
@ -174,10 +174,10 @@ Native Python classes can pick up new attributes dynamically:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> class Pet:
|
||||
... name = 'Molly'
|
||||
... name = "Molly"
|
||||
...
|
||||
>>> p = Pet()
|
||||
>>> p.name = 'Charly' # overwrite existing
|
||||
>>> p.name = "Charly" # overwrite existing
|
||||
>>> p.age = 2 # dynamically add a new attribute
|
||||
|
||||
By default, classes exported from C++ do not support this and the only writable
|
||||
@ -195,7 +195,7 @@ Trying to set any other attribute results in an error:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = example.Pet()
|
||||
>>> p.name = 'Charly' # OK, attribute defined in C++
|
||||
>>> p.name = "Charly" # OK, attribute defined in C++
|
||||
>>> p.age = 2 # fail
|
||||
AttributeError: 'Pet' object has no attribute 'age'
|
||||
|
||||
@ -213,7 +213,7 @@ Now everything works as expected:
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = example.Pet()
|
||||
>>> p.name = 'Charly' # OK, overwrite value in C++
|
||||
>>> p.name = "Charly" # OK, overwrite value in C++
|
||||
>>> p.age = 2 # OK, dynamically add a new attribute
|
||||
>>> p.__dict__ # just like a native Python class
|
||||
{'age': 2}
|
||||
@ -280,11 +280,11 @@ expose fields and methods of both types:
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = example.Dog('Molly')
|
||||
>>> p = example.Dog("Molly")
|
||||
>>> p.name
|
||||
u'Molly'
|
||||
'Molly'
|
||||
>>> p.bark()
|
||||
u'woof!'
|
||||
'woof!'
|
||||
|
||||
The C++ classes defined above are regular non-polymorphic types with an
|
||||
inheritance relationship. This is reflected in Python:
|
||||
@ -332,7 +332,7 @@ will automatically recognize this:
|
||||
>>> type(p)
|
||||
PolymorphicDog # automatically downcast
|
||||
>>> p.bark()
|
||||
u'woof!'
|
||||
'woof!'
|
||||
|
||||
Given a pointer to a polymorphic base, pybind11 performs automatic downcasting
|
||||
to the actual derived type. Note that this goes beyond the usual situation in
|
||||
@ -434,8 +434,7 @@ you can use ``py::detail::overload_cast_impl`` with an additional set of parenth
|
||||
.def("set", overload_cast_<int>()(&Pet::set), "Set the pet's age")
|
||||
.def("set", overload_cast_<const std::string &>()(&Pet::set), "Set the pet's name");
|
||||
|
||||
.. [#cpp14] A compiler which supports the ``-std=c++14`` flag
|
||||
or Visual Studio 2015 Update 2 and newer.
|
||||
.. [#cpp14] A compiler which supports the ``-std=c++14`` flag.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -446,8 +445,7 @@ you can use ``py::detail::overload_cast_impl`` with an additional set of parenth
|
||||
Enumerations and internal types
|
||||
===============================
|
||||
|
||||
Let's now suppose that the example class contains an internal enumeration type,
|
||||
e.g.:
|
||||
Let's now suppose that the example class contains internal types like enumerations, e.g.:
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
@ -457,10 +455,15 @@ e.g.:
|
||||
Cat
|
||||
};
|
||||
|
||||
struct Attributes {
|
||||
float age = 0;
|
||||
};
|
||||
|
||||
Pet(const std::string &name, Kind type) : name(name), type(type) { }
|
||||
|
||||
std::string name;
|
||||
Kind type;
|
||||
Attributes attr;
|
||||
};
|
||||
|
||||
The binding code for this example looks as follows:
|
||||
@ -471,22 +474,28 @@ The binding code for this example looks as follows:
|
||||
|
||||
pet.def(py::init<const std::string &, Pet::Kind>())
|
||||
.def_readwrite("name", &Pet::name)
|
||||
.def_readwrite("type", &Pet::type);
|
||||
.def_readwrite("type", &Pet::type)
|
||||
.def_readwrite("attr", &Pet::attr);
|
||||
|
||||
py::enum_<Pet::Kind>(pet, "Kind")
|
||||
.value("Dog", Pet::Kind::Dog)
|
||||
.value("Cat", Pet::Kind::Cat)
|
||||
.export_values();
|
||||
|
||||
To ensure that the ``Kind`` type is created within the scope of ``Pet``, the
|
||||
``pet`` :class:`class_` instance must be supplied to the :class:`enum_`.
|
||||
py::class_<Pet::Attributes>(pet, "Attributes")
|
||||
.def(py::init<>())
|
||||
.def_readwrite("age", &Pet::Attributes::age);
|
||||
|
||||
|
||||
To ensure that the nested types ``Kind`` and ``Attributes`` are created within the scope of ``Pet``, the
|
||||
``pet`` :class:`class_` instance must be supplied to the :class:`enum_` and :class:`class_`
|
||||
constructor. The :func:`enum_::export_values` function exports the enum entries
|
||||
into the parent scope, which should be skipped for newer C++11-style strongly
|
||||
typed enums.
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Pet('Lucy', Pet.Cat)
|
||||
>>> p = Pet("Lucy", Pet.Cat)
|
||||
>>> p.type
|
||||
Kind.Cat
|
||||
>>> int(p.type)
|
||||
@ -508,7 +517,7 @@ The ``name`` property returns the name of the enum value as a unicode string.
|
||||
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> p = Pet( "Lucy", Pet.Cat )
|
||||
>>> p = Pet("Lucy", Pet.Cat)
|
||||
>>> pet_type = p.type
|
||||
>>> pet_type
|
||||
Pet.Cat
|
||||
|
96
3rdparty/pybind11/docs/compiling.rst
vendored
96
3rdparty/pybind11/docs/compiling.rst
vendored
@ -42,10 +42,7 @@ An example of a ``setup.py`` using pybind11's helpers:
|
||||
),
|
||||
]
|
||||
|
||||
setup(
|
||||
...,
|
||||
ext_modules=ext_modules
|
||||
)
|
||||
setup(..., ext_modules=ext_modules)
|
||||
|
||||
If you want to do an automatic search for the highest supported C++ standard,
|
||||
that is supported via a ``build_ext`` command override; it will only affect
|
||||
@ -64,11 +61,20 @@ that is supported via a ``build_ext`` command override; it will only affect
|
||||
),
|
||||
]
|
||||
|
||||
setup(
|
||||
...,
|
||||
cmdclass={"build_ext": build_ext},
|
||||
ext_modules=ext_modules
|
||||
)
|
||||
setup(..., cmdclass={"build_ext": build_ext}, ext_modules=ext_modules)
|
||||
|
||||
If you have single-file extension modules that are directly stored in the
|
||||
Python source tree (``foo.cpp`` in the same directory as where a ``foo.py``
|
||||
would be located), you can also generate ``Pybind11Extensions`` using
|
||||
``setup_helpers.intree_extensions``: ``intree_extensions(["path/to/foo.cpp",
|
||||
...])`` returns a list of ``Pybind11Extensions`` which can be passed to
|
||||
``ext_modules``, possibly after further customizing their attributes
|
||||
(``libraries``, ``include_dirs``, etc.). By doing so, a ``foo.*.so`` extension
|
||||
module will be generated and made available upon installation.
|
||||
|
||||
``intree_extension`` will automatically detect if you are using a ``src``-style
|
||||
layout (as long as no namespace packages are involved), but you can also
|
||||
explicitly pass ``package_dir`` to it (as in ``setuptools.setup``).
|
||||
|
||||
Since pybind11 does not require NumPy when building, a light-weight replacement
|
||||
for NumPy's parallel compilation distutils tool is included. Use it like this:
|
||||
@ -84,22 +90,23 @@ for NumPy's parallel compilation distutils tool is included. Use it like this:
|
||||
|
||||
The argument is the name of an environment variable to control the number of
|
||||
threads, such as ``NPY_NUM_BUILD_JOBS`` (as used by NumPy), though you can set
|
||||
something different if you want. You can also pass ``default=N`` to set the
|
||||
default number of threads (0 will take the number of threads available) and
|
||||
``max=N``, the maximum number of threads; if you have a large extension you may
|
||||
want set this to a memory dependent number.
|
||||
something different if you want; ``CMAKE_BUILD_PARALLEL_LEVEL`` is another choice
|
||||
a user might expect. You can also pass ``default=N`` to set the default number
|
||||
of threads (0 will take the number of threads available) and ``max=N``, the
|
||||
maximum number of threads; if you have a large extension you may want set this
|
||||
to a memory dependent number.
|
||||
|
||||
If you are developing rapidly and have a lot of C++ files, you may want to
|
||||
avoid rebuilding files that have not changed. For simple cases were you are
|
||||
using ``pip install -e .`` and do not have local headers, you can skip the
|
||||
rebuild if a object file is newer than it's source (headers are not checked!)
|
||||
rebuild if an object file is newer than its source (headers are not checked!)
|
||||
with the following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pybind11.setup_helpers import ParallelCompile, naive_recompile
|
||||
|
||||
SmartCompile("NPY_NUM_BUILD_JOBS", needs_recompile=naive_recompile).install()
|
||||
ParallelCompile("NPY_NUM_BUILD_JOBS", needs_recompile=naive_recompile).install()
|
||||
|
||||
|
||||
If you have a more complex build, you can implement a smarter function and pass
|
||||
@ -136,7 +143,7 @@ Your ``pyproject.toml`` file will likely look something like this:
|
||||
.. code-block:: toml
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools", "wheel", "pybind11==2.6.0"]
|
||||
requires = ["setuptools>=42", "wheel", "pybind11~=2.6.1"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
.. note::
|
||||
@ -147,10 +154,12 @@ Your ``pyproject.toml`` file will likely look something like this:
|
||||
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.
|
||||
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:
|
||||
|
||||
@ -331,7 +340,7 @@ standard explicitly with
|
||||
|
||||
set(CMAKE_CXX_STANDARD 14 CACHE STRING "C++ version selection") # or 11, 14, 17, 20
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON) # optional, ensure standard is supported
|
||||
set(CMAKE_CXX_EXTENSIONS OFF) # optional, keep compiler extensionsn off
|
||||
set(CMAKE_CXX_EXTENSIONS OFF) # optional, keep compiler extensions off
|
||||
|
||||
The variables can also be set when calling CMake from the command line using
|
||||
the ``-D<variable>=<value>`` flag. You can also manually set ``CXX_STANDARD``
|
||||
@ -401,16 +410,17 @@ can refer to the same [cmake_example]_ repository for a full sample project
|
||||
FindPython mode
|
||||
---------------
|
||||
|
||||
CMake 3.12+ (3.15+ recommended) added a new module called FindPython that had a
|
||||
highly improved search algorithm and modern targets and tools. If you use
|
||||
FindPython, pybind11 will detect this and use the existing targets instead:
|
||||
CMake 3.12+ (3.15+ recommended, 3.18.2+ ideal) added a new module called
|
||||
FindPython that had a highly improved search algorithm and modern targets
|
||||
and tools. If you use FindPython, pybind11 will detect this and use the
|
||||
existing targets instead:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minumum_required(VERSION 3.15...3.18)
|
||||
cmake_minimum_required(VERSION 3.15...3.22)
|
||||
project(example LANGUAGES CXX)
|
||||
|
||||
find_package(Python COMPONENTS Interpreter Development REQUIRED)
|
||||
find_package(Python 3.6 COMPONENTS Interpreter Development REQUIRED)
|
||||
find_package(pybind11 CONFIG REQUIRED)
|
||||
# or add_subdirectory(pybind11)
|
||||
|
||||
@ -423,9 +433,8 @@ algorithms from the CMake invocation, with ``-DPYBIND11_FINDPYTHON=ON``.
|
||||
|
||||
.. warning::
|
||||
|
||||
If you use FindPython2 and FindPython3 to dual-target Python, use the
|
||||
individual targets listed below, and avoid targets that directly include
|
||||
Python parts.
|
||||
If you use FindPython to multi-target Python versions, use the individual
|
||||
targets listed below, and avoid targets that directly include Python parts.
|
||||
|
||||
There are `many ways to hint or force a discovery of a specific Python
|
||||
installation <https://cmake.org/cmake/help/latest/module/FindPython.html>`_),
|
||||
@ -433,6 +442,14 @@ setting ``Python_ROOT_DIR`` may be the most common one (though with
|
||||
virtualenv/venv support, and Conda support, this tends to find the correct
|
||||
Python version more often than the old system did).
|
||||
|
||||
.. warning::
|
||||
|
||||
When the Python libraries (i.e. ``libpythonXX.a`` and ``libpythonXX.so``
|
||||
on Unix) are not available, as is the case on a manylinux image, the
|
||||
``Development`` component will not be resolved by ``FindPython``. When not
|
||||
using the embedding functionality, CMake 3.18+ allows you to specify
|
||||
``Development.Module`` instead of ``Development`` to resolve this issue.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
Advanced: interface library targets
|
||||
@ -444,11 +461,8 @@ available in all modes. The targets provided are:
|
||||
``pybind11::headers``
|
||||
Just the pybind11 headers and minimum compile requirements
|
||||
|
||||
``pybind11::python2_no_register``
|
||||
Quiets the warning/error when mixing C++14 or higher and Python 2
|
||||
|
||||
``pybind11::pybind11``
|
||||
Python headers + ``pybind11::headers`` + ``pybind11::python2_no_register`` (Python 2 only)
|
||||
Python headers + ``pybind11::headers``
|
||||
|
||||
``pybind11::python_link_helper``
|
||||
Just the "linking" part of pybind11:module
|
||||
@ -457,7 +471,7 @@ available in all modes. The targets provided are:
|
||||
Everything for extension modules - ``pybind11::pybind11`` + ``Python::Module`` (FindPython CMake 3.15+) or ``pybind11::python_link_helper``
|
||||
|
||||
``pybind11::embed``
|
||||
Everything for embedding the Python interpreter - ``pybind11::pybind11`` + ``Python::Embed`` (FindPython) or Python libs
|
||||
Everything for embedding the Python interpreter - ``pybind11::pybind11`` + ``Python::Python`` (FindPython) or Python libs
|
||||
|
||||
``pybind11::lto`` / ``pybind11::thin_lto``
|
||||
An alternative to `INTERPROCEDURAL_OPTIMIZATION` for adding link-time optimization.
|
||||
@ -491,7 +505,10 @@ You can use these targets to build complex applications. For example, the
|
||||
target_link_libraries(example PRIVATE pybind11::module pybind11::lto pybind11::windows_extras)
|
||||
|
||||
pybind11_extension(example)
|
||||
pybind11_strip(example)
|
||||
if(NOT MSVC AND NOT ${CMAKE_BUILD_TYPE} MATCHES Debug|RelWithDebInfo)
|
||||
# Strip unnecessary sections of the binary on Linux/macOS
|
||||
pybind11_strip(example)
|
||||
endif()
|
||||
|
||||
set_target_properties(example PROPERTIES CXX_VISIBILITY_PRESET "hidden"
|
||||
CUDA_VISIBILITY_PRESET "hidden")
|
||||
@ -504,7 +521,7 @@ Instead of setting properties, you can set ``CMAKE_*`` variables to initialize t
|
||||
compiler flags are provided to ensure high quality code generation. In
|
||||
contrast to the ``pybind11_add_module()`` command, the CMake interface
|
||||
provides a *composable* set of targets to ensure that you retain flexibility.
|
||||
It can be expecially important to provide or set these properties; the
|
||||
It can be especially important to provide or set these properties; the
|
||||
:ref:`FAQ <faq:symhidden>` contains an explanation on why these are needed.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
@ -557,10 +574,7 @@ On Linux, you can compile an example such as the one given in
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ c++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`
|
||||
|
||||
The flags given here assume that you're using Python 3. For Python 2, just
|
||||
change the executable appropriately (to ``python`` or ``python2``).
|
||||
$ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
|
||||
|
||||
The ``python3 -m pybind11 --includes`` command fetches the include paths for
|
||||
both pybind11 and Python headers. This assumes that pybind11 has been installed
|
||||
@ -568,19 +582,13 @@ using ``pip`` or ``conda``. If it hasn't, you can also manually specify
|
||||
``-I <path-to-pybind11>/include`` together with the Python includes path
|
||||
``python3-config --includes``.
|
||||
|
||||
Note that Python 2.7 modules don't use a special suffix, so you should simply
|
||||
use ``example.so`` instead of ``example`python3-config --extension-suffix```.
|
||||
Besides, the ``--extension-suffix`` option may or may not be available, depending
|
||||
on the distribution; in the latter case, the module extension can be manually
|
||||
set to ``.so``.
|
||||
|
||||
On macOS: the build command is almost the same but it also requires passing
|
||||
the ``-undefined dynamic_lookup`` flag so as to ignore missing symbols when
|
||||
building the module:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`
|
||||
$ c++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
|
||||
|
||||
In general, it is advisable to include several additional build parameters
|
||||
that can considerably reduce the size of the created binary. Refer to section
|
||||
|
42
3rdparty/pybind11/docs/conf.py
vendored
42
3rdparty/pybind11/docs/conf.py
vendored
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# pybind11 documentation build configuration file, created by
|
||||
# sphinx-quickstart on Sun Oct 11 19:23:48 2015.
|
||||
@ -13,12 +12,11 @@
|
||||
# All configuration values have a default; values that are commented out
|
||||
# serve to show the default.
|
||||
|
||||
import sys
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
DIR = Path(__file__).parent.resolve()
|
||||
|
||||
@ -37,6 +35,7 @@ DIR = Path(__file__).parent.resolve()
|
||||
# ones.
|
||||
extensions = [
|
||||
"breathe",
|
||||
"sphinx_copybutton",
|
||||
"sphinxcontrib.rsvgconverter",
|
||||
"sphinxcontrib.moderncmakedomain",
|
||||
]
|
||||
@ -127,23 +126,7 @@ todo_include_todos = False
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
import sphinx_rtd_theme
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
html_context = {"css_files": ["_static/theme_overrides.css"]}
|
||||
else:
|
||||
html_context = {
|
||||
"css_files": [
|
||||
"//media.readthedocs.org/css/sphinx_rtd_theme.css",
|
||||
"//media.readthedocs.org/css/readthedocs-doc-embed.css",
|
||||
"_static/theme_overrides.css",
|
||||
]
|
||||
}
|
||||
html_theme = "furo"
|
||||
|
||||
# Theme options are theme-specific and customize the look and feel of a theme
|
||||
# further. For a list of options available for each theme, see the
|
||||
@ -174,6 +157,10 @@ else:
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ["_static"]
|
||||
|
||||
html_css_files = [
|
||||
"css/custom.css",
|
||||
]
|
||||
|
||||
# Add any extra paths that contain custom files (such as robots.txt or
|
||||
# .htaccess) here, relative to this directory. These files are copied
|
||||
# directly to the root of the documentation.
|
||||
@ -239,6 +226,8 @@ htmlhelp_basename = "pybind11doc"
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
latex_engine = "pdflatex"
|
||||
|
||||
latex_elements = {
|
||||
# The paper size ('letterpaper' or 'a4paper').
|
||||
# 'papersize': 'letterpaper',
|
||||
@ -344,17 +333,20 @@ def generate_doxygen_xml(app):
|
||||
subprocess.call(["doxygen", "--version"])
|
||||
retcode = subprocess.call(["doxygen"], cwd=app.confdir)
|
||||
if retcode < 0:
|
||||
sys.stderr.write("doxygen error code: {}\n".format(-retcode))
|
||||
sys.stderr.write(f"doxygen error code: {-retcode}\n")
|
||||
except OSError as e:
|
||||
sys.stderr.write("doxygen execution failed: {}\n".format(e))
|
||||
sys.stderr.write(f"doxygen execution failed: {e}\n")
|
||||
|
||||
|
||||
def prepare(app):
|
||||
with open(DIR.parent / "README.rst") as f:
|
||||
contents = f.read()
|
||||
|
||||
# Filter out section titles for index.rst for LaTeX
|
||||
if app.builder.name == "latex":
|
||||
# Remove badges and stuff from start
|
||||
contents = contents[contents.find(r".. start") :]
|
||||
|
||||
# Filter out section titles for index.rst for LaTeX
|
||||
contents = re.sub(r"^(.*)\n[-~]{3,}$", r"**\1**", contents, flags=re.MULTILINE)
|
||||
|
||||
with open(DIR / "readme.rst", "w") as f:
|
||||
|
52
3rdparty/pybind11/docs/faq.rst
vendored
52
3rdparty/pybind11/docs/faq.rst
vendored
@ -5,12 +5,10 @@ Frequently asked questions
|
||||
===========================================================
|
||||
|
||||
1. Make sure that the name specified in PYBIND11_MODULE is identical to the
|
||||
filename of the extension library (without suffixes such as .so)
|
||||
filename of the extension library (without suffixes such as ``.so``).
|
||||
|
||||
2. If the above did not fix the issue, you are likely using an incompatible
|
||||
version of Python (for instance, the extension library was compiled against
|
||||
Python 2, while the interpreter is running on top of some version of Python
|
||||
3, or vice versa).
|
||||
version of Python that does not match what you compiled with.
|
||||
|
||||
"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``"
|
||||
========================================================================
|
||||
@ -54,7 +52,7 @@ provided by the caller -- in fact, it does nothing at all.
|
||||
.. code-block:: python
|
||||
|
||||
def increment(i):
|
||||
i += 1 # nope..
|
||||
i += 1 # nope..
|
||||
|
||||
pybind11 is also affected by such language-level conventions, which means that
|
||||
binding ``increment`` or ``increment_ptr`` will also create Python functions
|
||||
@ -147,7 +145,7 @@ using C++14 template metaprogramming.
|
||||
|
||||
.. _`faq:hidden_visibility`:
|
||||
|
||||
"‘SomeClass’ declared with greater visibility than the type of its field ‘SomeClass::member’ [-Wattributes]"
|
||||
"'SomeClass' declared with greater visibility than the type of its field 'SomeClass::member' [-Wattributes]"
|
||||
============================================================================================================
|
||||
|
||||
This error typically indicates that you are compiling without the required
|
||||
@ -169,8 +167,8 @@ can be changed, but even if it isn't it is not always enough to guarantee
|
||||
complete independence of the symbols involved when not using
|
||||
``-fvisibility=hidden``.
|
||||
|
||||
Additionally, ``-fvisiblity=hidden`` can deliver considerably binary size
|
||||
savings. (See the following section for more details).
|
||||
Additionally, ``-fvisibility=hidden`` can deliver considerably binary size
|
||||
savings. (See the following section for more details.)
|
||||
|
||||
|
||||
.. _`faq:symhidden`:
|
||||
@ -180,7 +178,7 @@ How can I create smaller binaries?
|
||||
|
||||
To do its job, pybind11 extensively relies on a programming technique known as
|
||||
*template metaprogramming*, which is a way of performing computation at compile
|
||||
time using type information. Template metaprogamming usually instantiates code
|
||||
time using type information. Template metaprogramming usually instantiates code
|
||||
involving significant numbers of deeply nested types that are either completely
|
||||
removed or reduced to just a few instructions during the compiler's optimization
|
||||
phase. However, due to the nested nature of these types, the resulting symbol
|
||||
@ -222,20 +220,6 @@ In addition to decreasing binary size, ``-fvisibility=hidden`` also avoids
|
||||
potential serious issues when loading multiple modules and is required for
|
||||
proper pybind operation. See the previous FAQ entry for more details.
|
||||
|
||||
Working with ancient Visual Studio 2008 builds on Windows
|
||||
=========================================================
|
||||
|
||||
The official Windows distributions of Python are compiled using truly
|
||||
ancient versions of Visual Studio that lack good C++11 support. Some users
|
||||
implicitly assume that it would be impossible to load a plugin built with
|
||||
Visual Studio 2015 into a Python distribution that was compiled using Visual
|
||||
Studio 2008. However, no such issue exists: it's perfectly legitimate to
|
||||
interface DLLs that are built with different compilers and/or C libraries.
|
||||
Common gotchas to watch out for involve not ``free()``-ing memory region
|
||||
that that were ``malloc()``-ed in another shared library, using data
|
||||
structures with incompatible ABIs, and so on. pybind11 is very careful not
|
||||
to make these types of mistakes.
|
||||
|
||||
How can I properly handle Ctrl-C in long-running functions?
|
||||
===========================================================
|
||||
|
||||
@ -289,27 +273,7 @@ Conflicts can arise, however, when using pybind11 in a project that *also* uses
|
||||
the CMake Python detection in a system with several Python versions installed.
|
||||
|
||||
This difference may cause inconsistencies and errors if *both* mechanisms are
|
||||
used in the same project. Consider the following CMake code executed in a
|
||||
system with Python 2.7 and 3.x installed:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
find_package(PythonInterp)
|
||||
find_package(PythonLibs)
|
||||
find_package(pybind11)
|
||||
|
||||
It will detect Python 2.7 and pybind11 will pick it as well.
|
||||
|
||||
In contrast this code:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
find_package(pybind11)
|
||||
find_package(PythonInterp)
|
||||
find_package(PythonLibs)
|
||||
|
||||
will detect Python 3.x for pybind11 and may crash on
|
||||
``find_package(PythonLibs)`` afterwards.
|
||||
used in the same project.
|
||||
|
||||
There are three possible solutions:
|
||||
|
||||
|
4
3rdparty/pybind11/docs/installing.rst
vendored
4
3rdparty/pybind11/docs/installing.rst
vendored
@ -8,6 +8,8 @@ There are several ways to get the pybind11 source, which lives at
|
||||
developers recommend one of the first three ways listed here, submodule, PyPI,
|
||||
or conda-forge, for obtaining pybind11.
|
||||
|
||||
.. _include_as_a_submodule:
|
||||
|
||||
Include as a submodule
|
||||
======================
|
||||
|
||||
@ -16,7 +18,7 @@ as a submodule. From your git repository, use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
git submodule add ../../pybind/pybind11 extern/pybind11 -b stable
|
||||
git submodule add -b stable ../../pybind/pybind11 extern/pybind11
|
||||
git submodule update --init
|
||||
|
||||
This assumes you are placing your dependencies in ``extern/``, and that you are
|
||||
|
20
3rdparty/pybind11/docs/limitations.rst
vendored
20
3rdparty/pybind11/docs/limitations.rst
vendored
@ -57,16 +57,16 @@ clean, well written patch would likely be accepted to solve them.
|
||||
Python 3.9.0 warning
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Combining older versions of pybind11 (< 2.6.0) with Python on 3.9.0 will
|
||||
trigger undefined behavior that typically manifests as crashes during
|
||||
Combining older versions of pybind11 (< 2.6.0) with Python on exactly 3.9.0
|
||||
will trigger undefined behavior that typically manifests as crashes during
|
||||
interpreter shutdown (but could also destroy your data. **You have been
|
||||
warned**).
|
||||
|
||||
This issue has been
|
||||
`fixed in Python <https://github.com/python/cpython/pull/22670>`_. As a
|
||||
mitigation until 3.9.1 is released and commonly used, pybind11 (2.6.0 or newer)
|
||||
includes a temporary workaround specifically when Python 3.9.0 is detected at
|
||||
runtime, leaking about 50 bytes of memory when a callback function is garbage
|
||||
collected. For reference; the pybind11 test suite has about 2,000 such
|
||||
callbacks, but only 49 are garbage collected before the end-of-process. Wheels
|
||||
built with Python 3.9.0 will correctly avoid the leak when run in Python 3.9.1.
|
||||
This issue was `fixed in Python <https://github.com/python/cpython/pull/22670>`_.
|
||||
As a mitigation for this bug, pybind11 2.6.0 or newer includes a workaround
|
||||
specifically when Python 3.9.0 is detected at runtime, leaking about 50 bytes
|
||||
of memory when a callback function is garbage collected. For reference, the
|
||||
pybind11 test suite has about 2,000 such callbacks, but only 49 are garbage
|
||||
collected before the end-of-process. Wheels (even if built with Python 3.9.0)
|
||||
will correctly avoid the leak when run in Python 3.9.1, and this does not
|
||||
affect other 3.X versions.
|
||||
|
BIN
3rdparty/pybind11/docs/pybind11-logo.png
vendored
BIN
3rdparty/pybind11/docs/pybind11-logo.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 60 KiB |
15
3rdparty/pybind11/docs/reference.rst
vendored
15
3rdparty/pybind11/docs/reference.rst
vendored
@ -52,6 +52,20 @@ Convenience classes for specific Python types
|
||||
.. doxygengroup:: pytypes
|
||||
:members:
|
||||
|
||||
Convenience functions converting to Python types
|
||||
================================================
|
||||
|
||||
.. doxygenfunction:: make_tuple(Args&&...)
|
||||
|
||||
.. doxygenfunction:: make_iterator(Iterator, Sentinel, Extra &&...)
|
||||
.. doxygenfunction:: make_iterator(Type &, Extra&&...)
|
||||
|
||||
.. doxygenfunction:: make_key_iterator(Iterator, Sentinel, Extra &&...)
|
||||
.. doxygenfunction:: make_key_iterator(Type &, Extra&&...)
|
||||
|
||||
.. doxygenfunction:: make_value_iterator(Iterator, Sentinel, Extra &&...)
|
||||
.. doxygenfunction:: make_value_iterator(Type &, Extra&&...)
|
||||
|
||||
.. _extras:
|
||||
|
||||
Passing extra arguments to ``def`` or ``class_``
|
||||
@ -110,7 +124,6 @@ Exceptions
|
||||
.. doxygenclass:: builtin_exception
|
||||
:members:
|
||||
|
||||
|
||||
Literals
|
||||
========
|
||||
|
||||
|
80
3rdparty/pybind11/docs/release.rst
vendored
80
3rdparty/pybind11/docs/release.rst
vendored
@ -15,26 +15,37 @@ For example:
|
||||
|
||||
For beta, ``PYBIND11_VERSION_PATCH`` should be ``Z.b1``. RC's can be ``Z.rc1``.
|
||||
Always include the dot (even though PEP 440 allows it to be dropped). For a
|
||||
final release, this must be a simple integer.
|
||||
final release, this must be a simple integer. There is also a HEX version of
|
||||
the version just below.
|
||||
|
||||
|
||||
To release a new version of pybind11:
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you don't have nox, you should either use ``pipx run nox`` instead, or use
|
||||
``pipx install nox`` or ``brew install nox`` (Unix).
|
||||
|
||||
- Update the version number
|
||||
- Update ``PYBIND11_VERSION_MAJOR`` etc. in
|
||||
``include/pybind11/detail/common.h``. PATCH should be a simple integer.
|
||||
- Update ``pybind11/_version.py`` (match above)
|
||||
- Ensure that all the information in ``setup.py`` is up-to-date.
|
||||
- Add release date in ``docs/changelog.rst``.
|
||||
- ``git add`` and ``git commit``, ``git push``. **Ensure CI passes**. (If it
|
||||
fails due to a known flake issue, either ignore or restart CI.)
|
||||
- Add a release branch if this is a new minor version
|
||||
- ``git checkout -b vX.Y``, ``git push -u origin vX.Y``
|
||||
- Update ``PYBIND11_VERSION_MAJOR`` etc. in
|
||||
``include/pybind11/detail/common.h``. PATCH should be a simple integer.
|
||||
- Update the version HEX just below, as well.
|
||||
- Update ``pybind11/_version.py`` (match above)
|
||||
- Run ``nox -s tests_packaging`` to ensure this was done correctly.
|
||||
- Ensure that all the information in ``setup.cfg`` is up-to-date, like
|
||||
supported Python versions.
|
||||
- Add release date in ``docs/changelog.rst``.
|
||||
- Check to make sure
|
||||
`needs-changelog <https://github.com/pybind/pybind11/pulls?q=is%3Apr+is%3Aclosed+label%3A%22needs+changelog%22>`_
|
||||
issues are entered in the changelog (clear the label when done).
|
||||
- ``git add`` and ``git commit``, ``git push``. **Ensure CI passes**. (If it
|
||||
fails due to a known flake issue, either ignore or restart CI.)
|
||||
- Add a release branch if this is a new minor version, or update the existing release branch if it is a patch version
|
||||
- New branch: ``git checkout -b vX.Y``, ``git push -u origin vX.Y``
|
||||
- Update branch: ``git checkout vX.Y``, ``git merge <release branch>``, ``git push``
|
||||
- Update tags (optional; if you skip this, the GitHub release makes a
|
||||
non-annotated tag for you)
|
||||
- ``git tag -a vX.Y.Z -m 'vX.Y.Z release'``.
|
||||
- ``git push --tags``.
|
||||
non-annotated tag for you)
|
||||
- ``git tag -a vX.Y.Z -m 'vX.Y.Z release'``.
|
||||
- ``git push --tags``.
|
||||
- Update stable
|
||||
- ``git checkout stable``
|
||||
- ``git merge master``
|
||||
@ -42,25 +53,36 @@ To release a new version of pybind11:
|
||||
- Make a GitHub release (this shows up in the UI, sends new release
|
||||
notifications to users watching releases, and also uploads PyPI packages).
|
||||
(Note: if you do not use an existing tag, this creates a new lightweight tag
|
||||
for you, so you could skip the above step).
|
||||
- GUI method: click "Create a new release" on the far right, fill in the tag
|
||||
name (if you didn't tag above, it will be made here), fill in a release
|
||||
name like "Version X.Y.Z", and optionally copy-and-paste the changelog into
|
||||
the description (processed as markdown by Pandoc). Check "pre-release" if
|
||||
this is a beta/RC.
|
||||
- CLI method: with ``gh`` installed, run ``gh release create vX.Y.Z -t "Version X.Y.Z"``
|
||||
If this is a pre-release, add ``-p``.
|
||||
for you, so you could skip the above step.)
|
||||
- GUI method: Under `releases <https://github.com/pybind/pybind11/releases>`_
|
||||
click "Draft a new release" on the far right, fill in the tag name
|
||||
(if you didn't tag above, it will be made here), fill in a release name
|
||||
like "Version X.Y.Z", and copy-and-paste the markdown-formatted (!) changelog
|
||||
into the description (usually ``cat docs/changelog.rst | pandoc -f rst -t gfm``).
|
||||
Check "pre-release" if this is a beta/RC.
|
||||
- CLI method: with ``gh`` installed, run ``gh release create vX.Y.Z -t "Version X.Y.Z"``
|
||||
If this is a pre-release, add ``-p``.
|
||||
|
||||
- Get back to work
|
||||
- Make sure you are on master, not somewhere else: ``git checkout master``
|
||||
- Update version macros in ``include/pybind11/detail/common.h`` (set PATCH to
|
||||
``0.dev1`` and increment MINOR).
|
||||
- Update ``_version.py`` to match
|
||||
- Add a plot for in-development updates in ``docs/changelog.rst``.
|
||||
- ``git add``, ``git commit``, ``git push``
|
||||
- Make sure you are on master, not somewhere else: ``git checkout master``
|
||||
- Update version macros in ``include/pybind11/detail/common.h`` (set PATCH to
|
||||
``0.dev1`` and increment MINOR).
|
||||
- Update ``_version.py`` to match
|
||||
- Run ``nox -s tests_packaging`` to ensure this was done correctly.
|
||||
- Add a spot for in-development updates in ``docs/changelog.rst``.
|
||||
- ``git add``, ``git commit``, ``git push``
|
||||
|
||||
If a version branch is updated, remember to set PATCH to ``1.dev1``.
|
||||
|
||||
If you'd like to bump homebrew, run:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
brew bump-formula-pr --url https://github.com/pybind/pybind11/archive/vX.Y.Z.tar.gz
|
||||
|
||||
Conda-forge should automatically make a PR in a few hours, and automatically
|
||||
merge it if there are no issues.
|
||||
|
||||
|
||||
Manual packaging
|
||||
^^^^^^^^^^^^^^^^
|
||||
@ -69,9 +91,7 @@ If you need to manually upload releases, you can download the releases from the
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python3 -m pip install build
|
||||
python3 -m build
|
||||
PYBIND11_SDIST_GLOBAL=1 python3 -m build
|
||||
nox -s build
|
||||
twine upload dist/*
|
||||
|
||||
This makes SDists and wheels, and the final line uploads them.
|
||||
|
13
3rdparty/pybind11/docs/requirements.txt
vendored
13
3rdparty/pybind11/docs/requirements.txt
vendored
@ -1,7 +1,6 @@
|
||||
breathe==4.20.0
|
||||
commonmark==0.9.1
|
||||
recommonmark==0.6.0
|
||||
sphinx==3.2.1
|
||||
sphinx_rtd_theme==0.5.0
|
||||
sphinxcontrib-moderncmakedomain==3.13
|
||||
sphinxcontrib-svg2pdfconverter==1.1.0
|
||||
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
|
||||
|
46
3rdparty/pybind11/docs/upgrade.rst
vendored
46
3rdparty/pybind11/docs/upgrade.rst
vendored
@ -8,6 +8,46 @@ to a new version. But it goes into more detail. This includes things like
|
||||
deprecated APIs and their replacements, build system changes, general code
|
||||
modernization and other useful information.
|
||||
|
||||
.. _upgrade-guide-2.9:
|
||||
|
||||
v2.9
|
||||
====
|
||||
|
||||
* Any usage of the recently added ``py::make_simple_namespace`` should be
|
||||
converted to using ``py::module_::import("types").attr("SimpleNamespace")``
|
||||
instead.
|
||||
|
||||
* The use of ``_`` in custom type casters can now be replaced with the more
|
||||
readable ``const_name`` instead. The old ``_`` shortcut has been retained
|
||||
unless it is being used as a macro (like for gettext).
|
||||
|
||||
|
||||
.. _upgrade-guide-2.7:
|
||||
|
||||
v2.7
|
||||
====
|
||||
|
||||
*Before* v2.7, ``py::str`` can hold ``PyUnicodeObject`` or ``PyBytesObject``,
|
||||
and ``py::isinstance<str>()`` is ``true`` for both ``py::str`` and
|
||||
``py::bytes``. Starting with v2.7, ``py::str`` exclusively holds
|
||||
``PyUnicodeObject`` (`#2409 <https://github.com/pybind/pybind11/pull/2409>`_),
|
||||
and ``py::isinstance<str>()`` is ``true`` only for ``py::str``. To help in
|
||||
the transition of user code, the ``PYBIND11_STR_LEGACY_PERMISSIVE`` macro
|
||||
is provided as an escape hatch to go back to the legacy behavior. This macro
|
||||
will be removed in future releases. Two types of required fixes are expected
|
||||
to be common:
|
||||
|
||||
* Accidental use of ``py::str`` instead of ``py::bytes``, masked by the legacy
|
||||
behavior. These are probably very easy to fix, by changing from
|
||||
``py::str`` to ``py::bytes``.
|
||||
|
||||
* Reliance on py::isinstance<str>(obj) being ``true`` for
|
||||
``py::bytes``. This is likely to be easy to fix in most cases by adding
|
||||
``|| py::isinstance<bytes>(obj)``, but a fix may be more involved, e.g. if
|
||||
``py::isinstance<T>`` appears in a template. Such situations will require
|
||||
careful review and custom fixes.
|
||||
|
||||
|
||||
.. _upgrade-guide-2.6:
|
||||
|
||||
v2.6
|
||||
@ -192,7 +232,7 @@ way to get and set object state. See :ref:`pickling` for details.
|
||||
...
|
||||
.def(py::pickle(
|
||||
[](const Foo &self) { // __getstate__
|
||||
return py::make_tuple(f.value1(), f.value2(), ...); // unchanged
|
||||
return py::make_tuple(self.value1(), self.value2(), ...); // unchanged
|
||||
},
|
||||
[](py::tuple t) { // __setstate__, note: no `self` argument
|
||||
return new Foo(t[0].cast<std::string>(), ...);
|
||||
@ -256,7 +296,7 @@ Within pybind11's CMake build system, ``pybind11_add_module`` has always been
|
||||
setting the ``-fvisibility=hidden`` flag in release mode. From now on, it's
|
||||
being applied unconditionally, even in debug mode and it can no longer be opted
|
||||
out of with the ``NO_EXTRAS`` option. The ``pybind11::module`` target now also
|
||||
adds this flag to it's interface. The ``pybind11::embed`` target is unchanged.
|
||||
adds this flag to its interface. The ``pybind11::embed`` target is unchanged.
|
||||
|
||||
The most significant change here is for the ``pybind11::module`` target. If you
|
||||
were previously relying on default visibility, i.e. if your Python module was
|
||||
@ -484,7 +524,7 @@ include a declaration of the form:
|
||||
|
||||
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
|
||||
|
||||
Continuing to do so won’t cause an error or even a deprecation warning,
|
||||
Continuing to do so won't cause an error or even a deprecation warning,
|
||||
but it's completely redundant.
|
||||
|
||||
|
||||
|
355
3rdparty/pybind11/include/pybind11/attr.h
vendored
355
3rdparty/pybind11/include/pybind11/attr.h
vendored
@ -10,72 +10,113 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "detail/common.h"
|
||||
#include "cast.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
/// \addtogroup annotations
|
||||
/// @{
|
||||
|
||||
/// Annotation for methods
|
||||
struct is_method { handle class_; is_method(const handle &c) : class_(c) { } };
|
||||
struct is_method {
|
||||
handle class_;
|
||||
explicit is_method(const handle &c) : class_(c) {}
|
||||
};
|
||||
|
||||
/// Annotation for operators
|
||||
struct is_operator { };
|
||||
struct is_operator {};
|
||||
|
||||
/// Annotation for classes that cannot be subclassed
|
||||
struct is_final { };
|
||||
struct is_final {};
|
||||
|
||||
/// Annotation for parent scope
|
||||
struct scope { handle value; scope(const handle &s) : value(s) { } };
|
||||
struct scope {
|
||||
handle value;
|
||||
explicit scope(const handle &s) : value(s) {}
|
||||
};
|
||||
|
||||
/// Annotation for documentation
|
||||
struct doc { const char *value; doc(const char *value) : value(value) { } };
|
||||
struct doc {
|
||||
const char *value;
|
||||
explicit doc(const char *value) : value(value) {}
|
||||
};
|
||||
|
||||
/// Annotation for function names
|
||||
struct name { const char *value; name(const char *value) : value(value) { } };
|
||||
struct name {
|
||||
const char *value;
|
||||
explicit name(const char *value) : value(value) {}
|
||||
};
|
||||
|
||||
/// Annotation indicating that a function is an overload associated with a given "sibling"
|
||||
struct sibling { handle value; sibling(const handle &value) : value(value.ptr()) { } };
|
||||
struct sibling {
|
||||
handle value;
|
||||
explicit sibling(const handle &value) : value(value.ptr()) {}
|
||||
};
|
||||
|
||||
/// Annotation indicating that a class derives from another given type
|
||||
template <typename T> struct base {
|
||||
template <typename T>
|
||||
struct base {
|
||||
|
||||
PYBIND11_DEPRECATED("base<T>() was deprecated in favor of specifying 'T' as a template argument to class_")
|
||||
base() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute
|
||||
PYBIND11_DEPRECATED(
|
||||
"base<T>() was deprecated in favor of specifying 'T' as a template argument to class_")
|
||||
base() = default;
|
||||
};
|
||||
|
||||
/// Keep patient alive while nurse lives
|
||||
template <size_t Nurse, size_t Patient> struct keep_alive { };
|
||||
template <size_t Nurse, size_t Patient>
|
||||
struct keep_alive {};
|
||||
|
||||
/// Annotation indicating that a class is involved in a multiple inheritance relationship
|
||||
struct multiple_inheritance { };
|
||||
struct multiple_inheritance {};
|
||||
|
||||
/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class
|
||||
struct dynamic_attr { };
|
||||
struct dynamic_attr {};
|
||||
|
||||
/// Annotation which enables the buffer protocol for a type
|
||||
struct buffer_protocol { };
|
||||
struct buffer_protocol {};
|
||||
|
||||
/// Annotation which requests that a special metaclass is created for a type
|
||||
struct metaclass {
|
||||
handle value;
|
||||
|
||||
PYBIND11_DEPRECATED("py::metaclass() is no longer required. It's turned on by default now.")
|
||||
metaclass() { } // NOLINT(modernize-use-equals-default): breaks MSVC 2015 when adding an attribute
|
||||
metaclass() = default;
|
||||
|
||||
/// Override pybind11's default metaclass
|
||||
explicit metaclass(handle value) : value(value) { }
|
||||
explicit metaclass(handle value) : value(value) {}
|
||||
};
|
||||
|
||||
/// Specifies a custom callback with signature `void (PyHeapTypeObject*)` that
|
||||
/// may be used to customize the Python type.
|
||||
///
|
||||
/// The callback is invoked immediately before `PyType_Ready`.
|
||||
///
|
||||
/// Note: This is an advanced interface, and uses of it may require changes to
|
||||
/// work with later versions of pybind11. You may wish to consult the
|
||||
/// implementation of `make_new_python_type` in `detail/classes.h` to understand
|
||||
/// the context in which the callback will be run.
|
||||
struct custom_type_setup {
|
||||
using callback = std::function<void(PyHeapTypeObject *heap_type)>;
|
||||
|
||||
explicit custom_type_setup(callback value) : value(std::move(value)) {}
|
||||
|
||||
callback value;
|
||||
};
|
||||
|
||||
/// Annotation that marks a class as local to the module:
|
||||
struct module_local { const bool value; constexpr module_local(bool v = true) : value(v) { } };
|
||||
struct module_local {
|
||||
const bool value;
|
||||
constexpr explicit module_local(bool v = true) : value(v) {}
|
||||
};
|
||||
|
||||
/// Annotation to mark enums as an arithmetic type
|
||||
struct arithmetic { };
|
||||
struct arithmetic {};
|
||||
|
||||
/// Mark a function for addition at the beginning of the existing overload chain instead of the end
|
||||
struct prepend { };
|
||||
struct prepend {};
|
||||
|
||||
/** \rst
|
||||
A call policy which places one or more guard variables (``Ts...``) around the function call.
|
||||
@ -95,9 +136,13 @@ struct prepend { };
|
||||
return foo(args...); // forwarded arguments
|
||||
});
|
||||
\endrst */
|
||||
template <typename... Ts> struct call_guard;
|
||||
template <typename... Ts>
|
||||
struct call_guard;
|
||||
|
||||
template <> struct call_guard<> { using type = detail::void_type; };
|
||||
template <>
|
||||
struct call_guard<> {
|
||||
using type = detail::void_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct call_guard<T> {
|
||||
@ -122,8 +167,9 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
enum op_id : int;
|
||||
enum op_type : int;
|
||||
struct undefined_t;
|
||||
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t> struct op_;
|
||||
inline void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret);
|
||||
template <op_id id, op_type ot, typename L = undefined_t, typename R = undefined_t>
|
||||
struct op_;
|
||||
void keep_alive_impl(size_t Nurse, size_t Patient, function_call &call, handle ret);
|
||||
|
||||
/// Internal data structure which holds metadata about a keyword argument
|
||||
struct argument_record {
|
||||
@ -134,15 +180,16 @@ struct argument_record {
|
||||
bool none : 1; ///< True if None is allowed when loading
|
||||
|
||||
argument_record(const char *name, const char *descr, handle value, bool convert, bool none)
|
||||
: name(name), descr(descr), value(value), convert(convert), none(none) { }
|
||||
: name(name), descr(descr), value(value), convert(convert), none(none) {}
|
||||
};
|
||||
|
||||
/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.)
|
||||
/// Internal data structure which holds metadata about a bound function (signature, overloads,
|
||||
/// etc.)
|
||||
struct function_record {
|
||||
function_record()
|
||||
: is_constructor(false), is_new_style_constructor(false), is_stateless(false),
|
||||
is_operator(false), is_method(false), has_args(false),
|
||||
has_kwargs(false), has_kw_only_args(false), prepend(false) { }
|
||||
is_operator(false), is_method(false), has_args(false), has_kwargs(false),
|
||||
prepend(false) {}
|
||||
|
||||
/// Function name
|
||||
char *name = nullptr; /* why no C++ strings? They generate heavier code.. */
|
||||
@ -157,13 +204,13 @@ struct function_record {
|
||||
std::vector<argument_record> args;
|
||||
|
||||
/// Pointer to lambda function which converts arguments and performs the actual call
|
||||
handle (*impl) (function_call &) = nullptr;
|
||||
handle (*impl)(function_call &) = nullptr;
|
||||
|
||||
/// Storage for the wrapped function pointer and captured data, if any
|
||||
void *data[3] = { };
|
||||
void *data[3] = {};
|
||||
|
||||
/// Pointer to custom destructor for 'data' (if needed)
|
||||
void (*free_data) (function_record *ptr) = nullptr;
|
||||
void (*free_data)(function_record *ptr) = nullptr;
|
||||
|
||||
/// Return value policy associated with this function
|
||||
return_value_policy policy = return_value_policy::automatic;
|
||||
@ -189,17 +236,15 @@ struct function_record {
|
||||
/// True if the function has a '**kwargs' argument
|
||||
bool has_kwargs : 1;
|
||||
|
||||
/// True once a 'py::kw_only' is encountered (any following args are keyword-only)
|
||||
bool has_kw_only_args : 1;
|
||||
|
||||
/// True if this function is to be inserted at the beginning of the overload resolution chain
|
||||
bool prepend : 1;
|
||||
|
||||
/// Number of arguments (including py::args and/or py::kwargs, if present)
|
||||
std::uint16_t nargs;
|
||||
|
||||
/// Number of trailing arguments (counted in `nargs`) that are keyword-only
|
||||
std::uint16_t nargs_kw_only = 0;
|
||||
/// Number of leading positional arguments, which are terminated by a py::args or py::kwargs
|
||||
/// argument or by a py::kw_only annotation.
|
||||
std::uint16_t nargs_pos = 0;
|
||||
|
||||
/// Number of leading arguments (counted in `nargs`) that are positional-only
|
||||
std::uint16_t nargs_pos_only = 0;
|
||||
@ -221,7 +266,7 @@ struct function_record {
|
||||
struct type_record {
|
||||
PYBIND11_NOINLINE type_record()
|
||||
: multiple_inheritance(false), dynamic_attr(false), buffer_protocol(false),
|
||||
default_holder(true), module_local(false), is_final(false) { }
|
||||
default_holder(true), module_local(false), is_final(false) {}
|
||||
|
||||
/// Handle to the parent scope
|
||||
handle scope;
|
||||
@ -259,6 +304,9 @@ struct type_record {
|
||||
/// Custom metaclass (optional)
|
||||
handle metaclass;
|
||||
|
||||
/// Custom type setup.
|
||||
custom_type_setup::callback custom_type_setup_callback;
|
||||
|
||||
/// Multiple inheritance marker
|
||||
bool multiple_inheritance : 1;
|
||||
|
||||
@ -277,42 +325,45 @@ struct type_record {
|
||||
/// Is the class inheritable from python classes?
|
||||
bool is_final : 1;
|
||||
|
||||
PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *)) {
|
||||
auto base_info = detail::get_type_info(base, false);
|
||||
PYBIND11_NOINLINE void add_base(const std::type_info &base, void *(*caster)(void *) ) {
|
||||
auto *base_info = detail::get_type_info(base, false);
|
||||
if (!base_info) {
|
||||
std::string tname(base.name());
|
||||
detail::clean_type_id(tname);
|
||||
pybind11_fail("generic_type: type \"" + std::string(name) +
|
||||
"\" referenced unknown base type \"" + tname + "\"");
|
||||
pybind11_fail("generic_type: type \"" + std::string(name)
|
||||
+ "\" referenced unknown base type \"" + tname + "\"");
|
||||
}
|
||||
|
||||
if (default_holder != base_info->default_holder) {
|
||||
std::string tname(base.name());
|
||||
detail::clean_type_id(tname);
|
||||
pybind11_fail("generic_type: type \"" + std::string(name) + "\" " +
|
||||
(default_holder ? "does not have" : "has") +
|
||||
" a non-default holder type while its base \"" + tname + "\" " +
|
||||
(base_info->default_holder ? "does not" : "does"));
|
||||
pybind11_fail("generic_type: type \"" + std::string(name) + "\" "
|
||||
+ (default_holder ? "does not have" : "has")
|
||||
+ " a non-default holder type while its base \"" + tname + "\" "
|
||||
+ (base_info->default_holder ? "does not" : "does"));
|
||||
}
|
||||
|
||||
bases.append((PyObject *) base_info->type);
|
||||
|
||||
if (base_info->type->tp_dictoffset != 0)
|
||||
dynamic_attr = true;
|
||||
#if PY_VERSION_HEX < 0x030B0000
|
||||
dynamic_attr |= base_info->type->tp_dictoffset != 0;
|
||||
#else
|
||||
dynamic_attr |= (base_info->type->tp_flags & Py_TPFLAGS_MANAGED_DICT) != 0;
|
||||
#endif
|
||||
|
||||
if (caster)
|
||||
if (caster) {
|
||||
base_info->implicit_casts.emplace_back(type, caster);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline function_call::function_call(const function_record &f, handle p) :
|
||||
func(f), parent(p) {
|
||||
inline function_call::function_call(const function_record &f, handle p) : func(f), parent(p) {
|
||||
args.reserve(f.nargs);
|
||||
args_convert.reserve(f.nargs);
|
||||
}
|
||||
|
||||
/// Tag for a new-style `__init__` defined in `detail/init.h`
|
||||
struct is_new_style_constructor { };
|
||||
struct is_new_style_constructor {};
|
||||
|
||||
/**
|
||||
* Partial template specializations to process custom attributes provided to
|
||||
@ -320,129 +371,177 @@ struct is_new_style_constructor { };
|
||||
* fields in the type_record and function_record data structures or executed at
|
||||
* runtime to deal with custom call policies (e.g. keep_alive).
|
||||
*/
|
||||
template <typename T, typename SFINAE = void> struct process_attribute;
|
||||
template <typename T, typename SFINAE = void>
|
||||
struct process_attribute;
|
||||
|
||||
template <typename T> struct process_attribute_default {
|
||||
template <typename T>
|
||||
struct process_attribute_default {
|
||||
/// Default implementation: do nothing
|
||||
static void init(const T &, function_record *) { }
|
||||
static void init(const T &, type_record *) { }
|
||||
static void precall(function_call &) { }
|
||||
static void postcall(function_call &, handle) { }
|
||||
static void init(const T &, function_record *) {}
|
||||
static void init(const T &, type_record *) {}
|
||||
static void precall(function_call &) {}
|
||||
static void postcall(function_call &, handle) {}
|
||||
};
|
||||
|
||||
/// Process an attribute specifying the function's name
|
||||
template <> struct process_attribute<name> : process_attribute_default<name> {
|
||||
template <>
|
||||
struct process_attribute<name> : process_attribute_default<name> {
|
||||
static void init(const name &n, function_record *r) { r->name = const_cast<char *>(n.value); }
|
||||
};
|
||||
|
||||
/// Process an attribute specifying the function's docstring
|
||||
template <> struct process_attribute<doc> : process_attribute_default<doc> {
|
||||
template <>
|
||||
struct process_attribute<doc> : process_attribute_default<doc> {
|
||||
static void init(const doc &n, function_record *r) { r->doc = const_cast<char *>(n.value); }
|
||||
};
|
||||
|
||||
/// Process an attribute specifying the function's docstring (provided as a C-style string)
|
||||
template <> struct process_attribute<const char *> : process_attribute_default<const char *> {
|
||||
template <>
|
||||
struct process_attribute<const char *> : process_attribute_default<const char *> {
|
||||
static void init(const char *d, function_record *r) { r->doc = const_cast<char *>(d); }
|
||||
static void init(const char *d, type_record *r) { r->doc = const_cast<char *>(d); }
|
||||
};
|
||||
template <> struct process_attribute<char *> : process_attribute<const char *> { };
|
||||
template <>
|
||||
struct process_attribute<char *> : process_attribute<const char *> {};
|
||||
|
||||
/// Process an attribute indicating the function's return value policy
|
||||
template <> struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> {
|
||||
template <>
|
||||
struct process_attribute<return_value_policy> : process_attribute_default<return_value_policy> {
|
||||
static void init(const return_value_policy &p, function_record *r) { r->policy = p; }
|
||||
};
|
||||
|
||||
/// Process an attribute which indicates that this is an overloaded function associated with a given sibling
|
||||
template <> struct process_attribute<sibling> : process_attribute_default<sibling> {
|
||||
/// Process an attribute which indicates that this is an overloaded function associated with a
|
||||
/// given sibling
|
||||
template <>
|
||||
struct process_attribute<sibling> : process_attribute_default<sibling> {
|
||||
static void init(const sibling &s, function_record *r) { r->sibling = s.value; }
|
||||
};
|
||||
|
||||
/// Process an attribute which indicates that this function is a method
|
||||
template <> struct process_attribute<is_method> : process_attribute_default<is_method> {
|
||||
static void init(const is_method &s, function_record *r) { r->is_method = true; r->scope = s.class_; }
|
||||
template <>
|
||||
struct process_attribute<is_method> : process_attribute_default<is_method> {
|
||||
static void init(const is_method &s, function_record *r) {
|
||||
r->is_method = true;
|
||||
r->scope = s.class_;
|
||||
}
|
||||
};
|
||||
|
||||
/// Process an attribute which indicates the parent scope of a method
|
||||
template <> struct process_attribute<scope> : process_attribute_default<scope> {
|
||||
template <>
|
||||
struct process_attribute<scope> : process_attribute_default<scope> {
|
||||
static void init(const scope &s, function_record *r) { r->scope = s.value; }
|
||||
};
|
||||
|
||||
/// Process an attribute which indicates that this function is an operator
|
||||
template <> struct process_attribute<is_operator> : process_attribute_default<is_operator> {
|
||||
template <>
|
||||
struct process_attribute<is_operator> : process_attribute_default<is_operator> {
|
||||
static void init(const is_operator &, function_record *r) { r->is_operator = true; }
|
||||
};
|
||||
|
||||
template <> struct process_attribute<is_new_style_constructor> : process_attribute_default<is_new_style_constructor> {
|
||||
static void init(const is_new_style_constructor &, function_record *r) { r->is_new_style_constructor = true; }
|
||||
template <>
|
||||
struct process_attribute<is_new_style_constructor>
|
||||
: process_attribute_default<is_new_style_constructor> {
|
||||
static void init(const is_new_style_constructor &, function_record *r) {
|
||||
r->is_new_style_constructor = true;
|
||||
}
|
||||
};
|
||||
|
||||
inline void process_kw_only_arg(const arg &a, function_record *r) {
|
||||
if (!a.name || strlen(a.name) == 0)
|
||||
pybind11_fail("arg(): cannot specify an unnamed argument after an kw_only() annotation");
|
||||
++r->nargs_kw_only;
|
||||
inline void check_kw_only_arg(const arg &a, function_record *r) {
|
||||
if (r->args.size() > r->nargs_pos && (!a.name || a.name[0] == '\0')) {
|
||||
pybind11_fail("arg(): cannot specify an unnamed argument after a kw_only() annotation or "
|
||||
"args() argument");
|
||||
}
|
||||
}
|
||||
|
||||
inline void append_self_arg_if_needed(function_record *r) {
|
||||
if (r->is_method && r->args.empty()) {
|
||||
r->args.emplace_back("self", nullptr, handle(), /*convert=*/true, /*none=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
/// Process a keyword argument attribute (*without* a default value)
|
||||
template <> struct process_attribute<arg> : process_attribute_default<arg> {
|
||||
template <>
|
||||
struct process_attribute<arg> : process_attribute_default<arg> {
|
||||
static void init(const arg &a, function_record *r) {
|
||||
if (r->is_method && r->args.empty())
|
||||
r->args.emplace_back("self", nullptr, handle(), true /*convert*/, false /*none not allowed*/);
|
||||
append_self_arg_if_needed(r);
|
||||
r->args.emplace_back(a.name, nullptr, handle(), !a.flag_noconvert, a.flag_none);
|
||||
|
||||
if (r->has_kw_only_args) process_kw_only_arg(a, r);
|
||||
check_kw_only_arg(a, r);
|
||||
}
|
||||
};
|
||||
|
||||
/// Process a keyword argument attribute (*with* a default value)
|
||||
template <> struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||
template <>
|
||||
struct process_attribute<arg_v> : process_attribute_default<arg_v> {
|
||||
static void init(const arg_v &a, function_record *r) {
|
||||
if (r->is_method && r->args.empty())
|
||||
r->args.emplace_back("self", nullptr /*descr*/, handle() /*parent*/, true /*convert*/, false /*none not allowed*/);
|
||||
if (r->is_method && r->args.empty()) {
|
||||
r->args.emplace_back(
|
||||
"self", /*descr=*/nullptr, /*parent=*/handle(), /*convert=*/true, /*none=*/false);
|
||||
}
|
||||
|
||||
if (!a.value) {
|
||||
#if !defined(NDEBUG)
|
||||
#if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||
std::string descr("'");
|
||||
if (a.name) descr += std::string(a.name) + ": ";
|
||||
if (a.name) {
|
||||
descr += std::string(a.name) + ": ";
|
||||
}
|
||||
descr += a.type + "'";
|
||||
if (r->is_method) {
|
||||
if (r->name)
|
||||
descr += " in method '" + (std::string) str(r->scope) + "." + (std::string) r->name + "'";
|
||||
else
|
||||
if (r->name) {
|
||||
descr += " in method '" + (std::string) str(r->scope) + "."
|
||||
+ (std::string) r->name + "'";
|
||||
} else {
|
||||
descr += " in method of '" + (std::string) str(r->scope) + "'";
|
||||
}
|
||||
} else if (r->name) {
|
||||
descr += " in function '" + (std::string) r->name + "'";
|
||||
}
|
||||
pybind11_fail("arg(): could not convert default argument "
|
||||
+ descr + " into a Python object (type not registered yet?)");
|
||||
pybind11_fail("arg(): could not convert default argument " + descr
|
||||
+ " into a Python object (type not registered yet?)");
|
||||
#else
|
||||
pybind11_fail("arg(): could not convert default argument "
|
||||
"into a Python object (type not registered yet?). "
|
||||
"Compile in debug mode for more information.");
|
||||
"#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for "
|
||||
"more information.");
|
||||
#endif
|
||||
}
|
||||
r->args.emplace_back(a.name, a.descr, a.value.inc_ref(), !a.flag_noconvert, a.flag_none);
|
||||
|
||||
if (r->has_kw_only_args) process_kw_only_arg(a, r);
|
||||
check_kw_only_arg(a, r);
|
||||
}
|
||||
};
|
||||
|
||||
/// Process a keyword-only-arguments-follow pseudo argument
|
||||
template <> struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
||||
template <>
|
||||
struct process_attribute<kw_only> : process_attribute_default<kw_only> {
|
||||
static void init(const kw_only &, function_record *r) {
|
||||
r->has_kw_only_args = true;
|
||||
append_self_arg_if_needed(r);
|
||||
if (r->has_args && r->nargs_pos != static_cast<std::uint16_t>(r->args.size())) {
|
||||
pybind11_fail("Mismatched args() and kw_only(): they must occur at the same relative "
|
||||
"argument location (or omit kw_only() entirely)");
|
||||
}
|
||||
r->nargs_pos = static_cast<std::uint16_t>(r->args.size());
|
||||
}
|
||||
};
|
||||
|
||||
/// Process a positional-only-argument maker
|
||||
template <> struct process_attribute<pos_only> : process_attribute_default<pos_only> {
|
||||
template <>
|
||||
struct process_attribute<pos_only> : process_attribute_default<pos_only> {
|
||||
static void init(const pos_only &, function_record *r) {
|
||||
append_self_arg_if_needed(r);
|
||||
r->nargs_pos_only = static_cast<std::uint16_t>(r->args.size());
|
||||
if (r->nargs_pos_only > r->nargs_pos) {
|
||||
pybind11_fail("pos_only(): cannot follow a py::args() argument");
|
||||
}
|
||||
// It also can't follow a kw_only, but a static_assert in pybind11.h checks that
|
||||
}
|
||||
};
|
||||
|
||||
/// Process a parent class attribute. Single inheritance only (class_ itself already guarantees that)
|
||||
/// Process a parent class attribute. Single inheritance only (class_ itself already guarantees
|
||||
/// that)
|
||||
template <typename T>
|
||||
struct process_attribute<T, enable_if_t<is_pyobject<T>::value>> : process_attribute_default<handle> {
|
||||
struct process_attribute<T, enable_if_t<is_pyobject<T>::value>>
|
||||
: process_attribute_default<handle> {
|
||||
static void init(const handle &h, type_record *r) { r->bases.append(h); }
|
||||
};
|
||||
|
||||
@ -455,7 +554,9 @@ struct process_attribute<base<T>> : process_attribute_default<base<T>> {
|
||||
/// Process a multiple inheritance attribute
|
||||
template <>
|
||||
struct process_attribute<multiple_inheritance> : process_attribute_default<multiple_inheritance> {
|
||||
static void init(const multiple_inheritance &, type_record *r) { r->multiple_inheritance = true; }
|
||||
static void init(const multiple_inheritance &, type_record *r) {
|
||||
r->multiple_inheritance = true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
@ -463,6 +564,13 @@ struct process_attribute<dynamic_attr> : process_attribute_default<dynamic_attr>
|
||||
static void init(const dynamic_attr &, type_record *r) { r->dynamic_attr = true; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct process_attribute<custom_type_setup> {
|
||||
static void init(const custom_type_setup &value, type_record *r) {
|
||||
r->custom_type_setup_callback = value.value;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct process_attribute<is_final> : process_attribute_default<is_final> {
|
||||
static void init(const is_final &, type_record *r) { r->is_final = true; }
|
||||
@ -494,41 +602,59 @@ template <>
|
||||
struct process_attribute<arithmetic> : process_attribute_default<arithmetic> {};
|
||||
|
||||
template <typename... Ts>
|
||||
struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> { };
|
||||
struct process_attribute<call_guard<Ts...>> : process_attribute_default<call_guard<Ts...>> {};
|
||||
|
||||
/**
|
||||
* Process a keep_alive call policy -- invokes keep_alive_impl during the
|
||||
* pre-call handler if both Nurse, Patient != 0 and use the post-call handler
|
||||
* otherwise
|
||||
*/
|
||||
template <size_t Nurse, size_t Patient> struct process_attribute<keep_alive<Nurse, Patient>> : public process_attribute_default<keep_alive<Nurse, Patient>> {
|
||||
template <size_t Nurse, size_t Patient>
|
||||
struct process_attribute<keep_alive<Nurse, Patient>>
|
||||
: public process_attribute_default<keep_alive<Nurse, Patient>> {
|
||||
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0>
|
||||
static void precall(function_call &call) { keep_alive_impl(Nurse, Patient, call, handle()); }
|
||||
static void precall(function_call &call) {
|
||||
keep_alive_impl(Nurse, Patient, call, handle());
|
||||
}
|
||||
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N != 0 && P != 0, int> = 0>
|
||||
static void postcall(function_call &, handle) { }
|
||||
static void postcall(function_call &, handle) {}
|
||||
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0>
|
||||
static void precall(function_call &) { }
|
||||
static void precall(function_call &) {}
|
||||
template <size_t N = Nurse, size_t P = Patient, enable_if_t<N == 0 || P == 0, int> = 0>
|
||||
static void postcall(function_call &call, handle ret) { keep_alive_impl(Nurse, Patient, call, ret); }
|
||||
static void postcall(function_call &call, handle ret) {
|
||||
keep_alive_impl(Nurse, Patient, call, ret);
|
||||
}
|
||||
};
|
||||
|
||||
/// Recursively iterate over variadic template arguments
|
||||
template <typename... Args> struct process_attributes {
|
||||
static void init(const Args&... args, function_record *r) {
|
||||
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... };
|
||||
ignore_unused(unused);
|
||||
template <typename... Args>
|
||||
struct process_attributes {
|
||||
static void init(const Args &...args, function_record *r) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r);
|
||||
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r);
|
||||
using expander = int[];
|
||||
(void) expander{
|
||||
0, ((void) process_attribute<typename std::decay<Args>::type>::init(args, r), 0)...};
|
||||
}
|
||||
static void init(const Args&... args, type_record *r) {
|
||||
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::init(args, r), 0) ... };
|
||||
ignore_unused(unused);
|
||||
static void init(const Args &...args, type_record *r) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(r);
|
||||
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(r);
|
||||
using expander = int[];
|
||||
(void) expander{0,
|
||||
(process_attribute<typename std::decay<Args>::type>::init(args, r), 0)...};
|
||||
}
|
||||
static void precall(function_call &call) {
|
||||
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::precall(call), 0) ... };
|
||||
ignore_unused(unused);
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call);
|
||||
using expander = int[];
|
||||
(void) expander{0,
|
||||
(process_attribute<typename std::decay<Args>::type>::precall(call), 0)...};
|
||||
}
|
||||
static void postcall(function_call &call, handle fn_ret) {
|
||||
int unused[] = { 0, (process_attribute<typename std::decay<Args>::type>::postcall(call, fn_ret), 0) ... };
|
||||
ignore_unused(unused);
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(call, fn_ret);
|
||||
PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(fn_ret);
|
||||
using expander = int[];
|
||||
(void) expander{
|
||||
0, (process_attribute<typename std::decay<Args>::type>::postcall(call, fn_ret), 0)...};
|
||||
}
|
||||
};
|
||||
|
||||
@ -542,9 +668,10 @@ using extract_guard_t = typename exactly_one_t<is_call_guard, call_guard<>, Extr
|
||||
/// Check the number of named arguments at compile time
|
||||
template <typename... Extra,
|
||||
size_t named = constexpr_sum(std::is_base_of<arg, Extra>::value...),
|
||||
size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)>
|
||||
size_t self = constexpr_sum(std::is_same<is_method, Extra>::value...)>
|
||||
constexpr bool expected_num_args(size_t nargs, bool has_args, bool has_kwargs) {
|
||||
return named == 0 || (self + named + has_args + has_kwargs) == nargs;
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(nargs, has_args, has_kwargs);
|
||||
return named == 0 || (self + named + size_t(has_args) + size_t(has_kwargs)) == nargs;
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
129
3rdparty/pybind11/include/pybind11/buffer_info.h
vendored
129
3rdparty/pybind11/include/pybind11/buffer_info.h
vendored
@ -19,9 +19,11 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
|
||||
auto ndim = shape.size();
|
||||
std::vector<ssize_t> strides(ndim, itemsize);
|
||||
if (ndim > 0)
|
||||
for (size_t i = ndim - 1; i > 0; --i)
|
||||
if (ndim > 0) {
|
||||
for (size_t i = ndim - 1; i > 0; --i) {
|
||||
strides[i - 1] = strides[i] * shape[i];
|
||||
}
|
||||
}
|
||||
return strides;
|
||||
}
|
||||
|
||||
@ -29,8 +31,9 @@ inline std::vector<ssize_t> c_strides(const std::vector<ssize_t> &shape, ssize_t
|
||||
inline std::vector<ssize_t> f_strides(const std::vector<ssize_t> &shape, ssize_t itemsize) {
|
||||
auto ndim = shape.size();
|
||||
std::vector<ssize_t> strides(ndim, itemsize);
|
||||
for (size_t i = 1; i < ndim; ++i)
|
||||
for (size_t i = 1; i < ndim; ++i) {
|
||||
strides[i] = strides[i - 1] * shape[i - 1];
|
||||
}
|
||||
return strides;
|
||||
}
|
||||
|
||||
@ -41,61 +44,89 @@ struct buffer_info {
|
||||
void *ptr = nullptr; // Pointer to the underlying storage
|
||||
ssize_t itemsize = 0; // Size of individual items in bytes
|
||||
ssize_t size = 0; // Total number of entries
|
||||
std::string format; // For homogeneous buffers, this should be set to format_descriptor<T>::format()
|
||||
std::string format; // For homogeneous buffers, this should be set to
|
||||
// format_descriptor<T>::format()
|
||||
ssize_t ndim = 0; // Number of dimensions
|
||||
std::vector<ssize_t> shape; // Shape of the tensor (1 entry per dimension)
|
||||
std::vector<ssize_t> strides; // Number of bytes between adjacent entries (for each per dimension)
|
||||
std::vector<ssize_t> strides; // Number of bytes between adjacent entries
|
||||
// (for each per dimension)
|
||||
bool readonly = false; // flag to indicate if the underlying storage may be written to
|
||||
|
||||
buffer_info() = default;
|
||||
|
||||
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
|
||||
detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
|
||||
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
|
||||
shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
|
||||
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size())
|
||||
buffer_info(void *ptr,
|
||||
ssize_t itemsize,
|
||||
const std::string &format,
|
||||
ssize_t ndim,
|
||||
detail::any_container<ssize_t> shape_in,
|
||||
detail::any_container<ssize_t> strides_in,
|
||||
bool readonly = false)
|
||||
: ptr(ptr), itemsize(itemsize), size(1), format(format), ndim(ndim),
|
||||
shape(std::move(shape_in)), strides(std::move(strides_in)), readonly(readonly) {
|
||||
if (ndim != (ssize_t) shape.size() || ndim != (ssize_t) strides.size()) {
|
||||
pybind11_fail("buffer_info: ndim doesn't match shape and/or strides length");
|
||||
for (size_t i = 0; i < (size_t) ndim; ++i)
|
||||
}
|
||||
for (size_t i = 0; i < (size_t) ndim; ++i) {
|
||||
size *= shape[i];
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
buffer_info(T *ptr, detail::any_container<ssize_t> shape_in, detail::any_container<ssize_t> strides_in, bool readonly=false)
|
||||
: buffer_info(private_ctr_tag(), ptr, sizeof(T), format_descriptor<T>::format(), static_cast<ssize_t>(shape_in->size()), std::move(shape_in), std::move(strides_in), readonly) { }
|
||||
buffer_info(T *ptr,
|
||||
detail::any_container<ssize_t> shape_in,
|
||||
detail::any_container<ssize_t> strides_in,
|
||||
bool readonly = false)
|
||||
: buffer_info(private_ctr_tag(),
|
||||
ptr,
|
||||
sizeof(T),
|
||||
format_descriptor<T>::format(),
|
||||
static_cast<ssize_t>(shape_in->size()),
|
||||
std::move(shape_in),
|
||||
std::move(strides_in),
|
||||
readonly) {}
|
||||
|
||||
buffer_info(void *ptr, ssize_t itemsize, const std::string &format, ssize_t size, bool readonly=false)
|
||||
: buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) { }
|
||||
buffer_info(void *ptr,
|
||||
ssize_t itemsize,
|
||||
const std::string &format,
|
||||
ssize_t size,
|
||||
bool readonly = false)
|
||||
: buffer_info(ptr, itemsize, format, 1, {size}, {itemsize}, readonly) {}
|
||||
|
||||
template <typename T>
|
||||
buffer_info(T *ptr, ssize_t size, bool readonly=false)
|
||||
: buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) { }
|
||||
buffer_info(T *ptr, ssize_t size, bool readonly = false)
|
||||
: buffer_info(ptr, sizeof(T), format_descriptor<T>::format(), size, readonly) {}
|
||||
|
||||
template <typename T>
|
||||
buffer_info(const T *ptr, ssize_t size, bool readonly=true)
|
||||
: buffer_info(const_cast<T*>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) { }
|
||||
buffer_info(const T *ptr, ssize_t size, bool readonly = true)
|
||||
: buffer_info(
|
||||
const_cast<T *>(ptr), sizeof(T), format_descriptor<T>::format(), size, readonly) {}
|
||||
|
||||
explicit buffer_info(Py_buffer *view, bool ownview = true)
|
||||
: buffer_info(view->buf, view->itemsize, view->format, view->ndim,
|
||||
: buffer_info(
|
||||
view->buf,
|
||||
view->itemsize,
|
||||
view->format,
|
||||
view->ndim,
|
||||
{view->shape, view->shape + view->ndim},
|
||||
/* Though buffer::request() requests PyBUF_STRIDES, ctypes objects
|
||||
* ignore this flag and return a view with NULL strides.
|
||||
* When strides are NULL, build them manually. */
|
||||
view->strides
|
||||
? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
|
||||
: detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
|
||||
view->readonly) {
|
||||
? std::vector<ssize_t>(view->strides, view->strides + view->ndim)
|
||||
: detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize),
|
||||
(view->readonly != 0)) {
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
this->m_view = view;
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
this->ownview = ownview;
|
||||
}
|
||||
|
||||
buffer_info(const buffer_info &) = delete;
|
||||
buffer_info& operator=(const buffer_info &) = delete;
|
||||
buffer_info &operator=(const buffer_info &) = delete;
|
||||
|
||||
buffer_info(buffer_info &&other) {
|
||||
(*this) = std::move(other);
|
||||
}
|
||||
buffer_info(buffer_info &&other) noexcept { (*this) = std::move(other); }
|
||||
|
||||
buffer_info& operator=(buffer_info &&rhs) {
|
||||
buffer_info &operator=(buffer_info &&rhs) noexcept {
|
||||
ptr = rhs.ptr;
|
||||
itemsize = rhs.itemsize;
|
||||
size = rhs.size;
|
||||
@ -110,17 +141,28 @@ struct buffer_info {
|
||||
}
|
||||
|
||||
~buffer_info() {
|
||||
if (m_view && ownview) { PyBuffer_Release(m_view); delete m_view; }
|
||||
if (m_view && ownview) {
|
||||
PyBuffer_Release(m_view);
|
||||
delete m_view;
|
||||
}
|
||||
}
|
||||
|
||||
Py_buffer *view() const { return m_view; }
|
||||
Py_buffer *&view() { return m_view; }
|
||||
private:
|
||||
struct private_ctr_tag { };
|
||||
|
||||
buffer_info(private_ctr_tag, void *ptr, ssize_t itemsize, const std::string &format, ssize_t ndim,
|
||||
detail::any_container<ssize_t> &&shape_in, detail::any_container<ssize_t> &&strides_in, bool readonly)
|
||||
: buffer_info(ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) { }
|
||||
private:
|
||||
struct private_ctr_tag {};
|
||||
|
||||
buffer_info(private_ctr_tag,
|
||||
void *ptr,
|
||||
ssize_t itemsize,
|
||||
const std::string &format,
|
||||
ssize_t ndim,
|
||||
detail::any_container<ssize_t> &&shape_in,
|
||||
detail::any_container<ssize_t> &&strides_in,
|
||||
bool readonly)
|
||||
: buffer_info(
|
||||
ptr, itemsize, format, ndim, std::move(shape_in), std::move(strides_in), readonly) {}
|
||||
|
||||
Py_buffer *m_view = nullptr;
|
||||
bool ownview = false;
|
||||
@ -128,17 +170,22 @@ private:
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
template <typename T, typename SFINAE = void> struct compare_buffer_info {
|
||||
static bool compare(const buffer_info& b) {
|
||||
template <typename T, typename SFINAE = void>
|
||||
struct compare_buffer_info {
|
||||
static bool compare(const buffer_info &b) {
|
||||
return b.format == format_descriptor<T>::format() && b.itemsize == (ssize_t) sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
|
||||
static bool compare(const buffer_info& b) {
|
||||
return (size_t) b.itemsize == sizeof(T) && (b.format == format_descriptor<T>::value ||
|
||||
((sizeof(T) == sizeof(long)) && b.format == (std::is_unsigned<T>::value ? "L" : "l")) ||
|
||||
((sizeof(T) == sizeof(size_t)) && b.format == (std::is_unsigned<T>::value ? "N" : "n")));
|
||||
template <typename T>
|
||||
struct compare_buffer_info<T, detail::enable_if_t<std::is_integral<T>::value>> {
|
||||
static bool compare(const buffer_info &b) {
|
||||
return (size_t) b.itemsize == sizeof(T)
|
||||
&& (b.format == format_descriptor<T>::value
|
||||
|| ((sizeof(T) == sizeof(long))
|
||||
&& b.format == (std::is_unsigned<T>::value ? "L" : "l"))
|
||||
|| ((sizeof(T) == sizeof(size_t))
|
||||
&& b.format == (std::is_unsigned<T>::value ? "N" : "n")));
|
||||
}
|
||||
};
|
||||
|
||||
|
2206
3rdparty/pybind11/include/pybind11/cast.h
vendored
2206
3rdparty/pybind11/include/pybind11/cast.h
vendored
File diff suppressed because it is too large
Load Diff
170
3rdparty/pybind11/include/pybind11/chrono.h
vendored
170
3rdparty/pybind11/include/pybind11/chrono.h
vendored
@ -11,62 +11,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <cmath>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <datetime.h>
|
||||
|
||||
// Backport the PyDateTime_DELTA functions from Python3.3 if required
|
||||
#ifndef PyDateTime_DELTA_GET_DAYS
|
||||
#define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days)
|
||||
#endif
|
||||
#ifndef PyDateTime_DELTA_GET_SECONDS
|
||||
#define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds)
|
||||
#endif
|
||||
#ifndef PyDateTime_DELTA_GET_MICROSECONDS
|
||||
#define PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds)
|
||||
#endif
|
||||
#include <mutex>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
template <typename type> class duration_caster {
|
||||
template <typename type>
|
||||
class duration_caster {
|
||||
public:
|
||||
using rep = typename type::rep;
|
||||
using period = typename type::period;
|
||||
|
||||
using days = std::chrono::duration<uint_fast32_t, std::ratio<86400>>;
|
||||
// signed 25 bits required by the standard.
|
||||
using days = std::chrono::duration<int_least32_t, std::ratio<86400>>;
|
||||
|
||||
bool load(handle src, bool) {
|
||||
using namespace std::chrono;
|
||||
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
if (!PyDateTimeAPI) {
|
||||
PyDateTime_IMPORT;
|
||||
}
|
||||
|
||||
if (!src) return false;
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
// If invoked with datetime.delta object
|
||||
if (PyDelta_Check(src.ptr())) {
|
||||
value = type(duration_cast<duration<rep, period>>(
|
||||
days(PyDateTime_DELTA_GET_DAYS(src.ptr()))
|
||||
days(PyDateTime_DELTA_GET_DAYS(src.ptr()))
|
||||
+ seconds(PyDateTime_DELTA_GET_SECONDS(src.ptr()))
|
||||
+ microseconds(PyDateTime_DELTA_GET_MICROSECONDS(src.ptr()))));
|
||||
return true;
|
||||
}
|
||||
// If invoked with a float we assume it is seconds and convert
|
||||
else if (PyFloat_Check(src.ptr())) {
|
||||
value = type(duration_cast<duration<rep, period>>(duration<double>(PyFloat_AsDouble(src.ptr()))));
|
||||
if (PyFloat_Check(src.ptr())) {
|
||||
value = type(duration_cast<duration<rep, period>>(
|
||||
duration<double>(PyFloat_AsDouble(src.ptr()))));
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is a duration just return it back
|
||||
static const std::chrono::duration<rep, period>& get_duration(const std::chrono::duration<rep, period> &src) {
|
||||
static const std::chrono::duration<rep, period> &
|
||||
get_duration(const std::chrono::duration<rep, period> &src) {
|
||||
return src;
|
||||
}
|
||||
|
||||
// If this is a time_point get the time_since_epoch
|
||||
template <typename Clock> static std::chrono::duration<rep, period> get_duration(const std::chrono::time_point<Clock, std::chrono::duration<rep, period>> &src) {
|
||||
template <typename Clock>
|
||||
static std::chrono::duration<rep, period>
|
||||
get_duration(const std::chrono::time_point<Clock, std::chrono::duration<rep, period>> &src) {
|
||||
return src.time_since_epoch();
|
||||
}
|
||||
|
||||
@ -78,9 +79,12 @@ public:
|
||||
auto d = get_duration(src);
|
||||
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
if (!PyDateTimeAPI) {
|
||||
PyDateTime_IMPORT;
|
||||
}
|
||||
|
||||
// Declare these special duration types so the conversions happen with the correct primitive types (int)
|
||||
// Declare these special duration types so the conversions happen with the correct
|
||||
// primitive types (int)
|
||||
using dd_t = duration<int, std::ratio<86400>>;
|
||||
using ss_t = duration<int, std::ratio<1>>;
|
||||
using us_t = duration<int, std::micro>;
|
||||
@ -92,79 +96,109 @@ public:
|
||||
return PyDelta_FromDSU(dd.count(), ss.count(), us.count());
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(type, _("datetime.timedelta"));
|
||||
PYBIND11_TYPE_CASTER(type, const_name("datetime.timedelta"));
|
||||
};
|
||||
|
||||
inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) {
|
||||
#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || defined(_MSC_VER)
|
||||
if (localtime_s(buf, time))
|
||||
return nullptr;
|
||||
return buf;
|
||||
#else
|
||||
static std::mutex mtx;
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::tm *tm_ptr = std::localtime(time);
|
||||
if (tm_ptr != nullptr) {
|
||||
*buf = *tm_ptr;
|
||||
}
|
||||
return tm_ptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is for casting times on the system clock into datetime.datetime instances
|
||||
template <typename Duration> class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> {
|
||||
template <typename Duration>
|
||||
class type_caster<std::chrono::time_point<std::chrono::system_clock, Duration>> {
|
||||
public:
|
||||
using type = std::chrono::time_point<std::chrono::system_clock, Duration>;
|
||||
bool load(handle src, bool) {
|
||||
using namespace std::chrono;
|
||||
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
if (!PyDateTimeAPI) {
|
||||
PyDateTime_IMPORT;
|
||||
}
|
||||
|
||||
if (!src) return false;
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::tm cal;
|
||||
microseconds msecs;
|
||||
|
||||
if (PyDateTime_Check(src.ptr())) {
|
||||
cal.tm_sec = PyDateTime_DATE_GET_SECOND(src.ptr());
|
||||
cal.tm_min = PyDateTime_DATE_GET_MINUTE(src.ptr());
|
||||
cal.tm_hour = PyDateTime_DATE_GET_HOUR(src.ptr());
|
||||
cal.tm_mday = PyDateTime_GET_DAY(src.ptr());
|
||||
cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1;
|
||||
cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900;
|
||||
cal.tm_sec = PyDateTime_DATE_GET_SECOND(src.ptr());
|
||||
cal.tm_min = PyDateTime_DATE_GET_MINUTE(src.ptr());
|
||||
cal.tm_hour = PyDateTime_DATE_GET_HOUR(src.ptr());
|
||||
cal.tm_mday = PyDateTime_GET_DAY(src.ptr());
|
||||
cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1;
|
||||
cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900;
|
||||
cal.tm_isdst = -1;
|
||||
msecs = microseconds(PyDateTime_DATE_GET_MICROSECOND(src.ptr()));
|
||||
msecs = microseconds(PyDateTime_DATE_GET_MICROSECOND(src.ptr()));
|
||||
} else if (PyDate_Check(src.ptr())) {
|
||||
cal.tm_sec = 0;
|
||||
cal.tm_min = 0;
|
||||
cal.tm_hour = 0;
|
||||
cal.tm_mday = PyDateTime_GET_DAY(src.ptr());
|
||||
cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1;
|
||||
cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900;
|
||||
cal.tm_sec = 0;
|
||||
cal.tm_min = 0;
|
||||
cal.tm_hour = 0;
|
||||
cal.tm_mday = PyDateTime_GET_DAY(src.ptr());
|
||||
cal.tm_mon = PyDateTime_GET_MONTH(src.ptr()) - 1;
|
||||
cal.tm_year = PyDateTime_GET_YEAR(src.ptr()) - 1900;
|
||||
cal.tm_isdst = -1;
|
||||
msecs = microseconds(0);
|
||||
msecs = microseconds(0);
|
||||
} else if (PyTime_Check(src.ptr())) {
|
||||
cal.tm_sec = PyDateTime_TIME_GET_SECOND(src.ptr());
|
||||
cal.tm_min = PyDateTime_TIME_GET_MINUTE(src.ptr());
|
||||
cal.tm_hour = PyDateTime_TIME_GET_HOUR(src.ptr());
|
||||
cal.tm_mday = 1; // This date (day, month, year) = (1, 0, 70)
|
||||
cal.tm_mon = 0; // represents 1-Jan-1970, which is the first
|
||||
cal.tm_year = 70; // earliest available date for Python's datetime
|
||||
cal.tm_sec = PyDateTime_TIME_GET_SECOND(src.ptr());
|
||||
cal.tm_min = PyDateTime_TIME_GET_MINUTE(src.ptr());
|
||||
cal.tm_hour = PyDateTime_TIME_GET_HOUR(src.ptr());
|
||||
cal.tm_mday = 1; // This date (day, month, year) = (1, 0, 70)
|
||||
cal.tm_mon = 0; // represents 1-Jan-1970, which is the first
|
||||
cal.tm_year = 70; // earliest available date for Python's datetime
|
||||
cal.tm_isdst = -1;
|
||||
msecs = microseconds(PyDateTime_TIME_GET_MICROSECOND(src.ptr()));
|
||||
msecs = microseconds(PyDateTime_TIME_GET_MICROSECOND(src.ptr()));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
else return false;
|
||||
|
||||
value = time_point_cast<Duration>(system_clock::from_time_t(std::mktime(&cal)) + msecs);
|
||||
return true;
|
||||
}
|
||||
|
||||
static handle cast(const std::chrono::time_point<std::chrono::system_clock, Duration> &src, return_value_policy /* policy */, handle /* parent */) {
|
||||
static handle cast(const std::chrono::time_point<std::chrono::system_clock, Duration> &src,
|
||||
return_value_policy /* policy */,
|
||||
handle /* parent */) {
|
||||
using namespace std::chrono;
|
||||
|
||||
// Lazy initialise the PyDateTime import
|
||||
if (!PyDateTimeAPI) { PyDateTime_IMPORT; }
|
||||
if (!PyDateTimeAPI) {
|
||||
PyDateTime_IMPORT;
|
||||
}
|
||||
|
||||
// Get out microseconds, and make sure they are positive, to avoid bug in eastern hemisphere time zones
|
||||
// (cfr. https://github.com/pybind/pybind11/issues/2417)
|
||||
// Get out microseconds, and make sure they are positive, to avoid bug in eastern
|
||||
// hemisphere time zones (cfr. https://github.com/pybind/pybind11/issues/2417)
|
||||
using us_t = duration<int, std::micro>;
|
||||
auto us = duration_cast<us_t>(src.time_since_epoch() % seconds(1));
|
||||
if (us.count() < 0)
|
||||
if (us.count() < 0) {
|
||||
us += seconds(1);
|
||||
}
|
||||
|
||||
// Subtract microseconds BEFORE `system_clock::to_time_t`, because:
|
||||
// > If std::time_t has lower precision, it is implementation-defined whether the value is rounded or truncated.
|
||||
// (https://en.cppreference.com/w/cpp/chrono/system_clock/to_time_t)
|
||||
std::time_t tt = system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us));
|
||||
// this function uses static memory so it's best to copy it out asap just in case
|
||||
// otherwise other code that is using localtime may break this (not just python code)
|
||||
std::tm localtime = *std::localtime(&tt);
|
||||
// > If std::time_t has lower precision, it is implementation-defined whether the value is
|
||||
// rounded or truncated. (https://en.cppreference.com/w/cpp/chrono/system_clock/to_time_t)
|
||||
std::time_t tt
|
||||
= system_clock::to_time_t(time_point_cast<system_clock::duration>(src - us));
|
||||
|
||||
std::tm localtime;
|
||||
std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime);
|
||||
if (!localtime_ptr) {
|
||||
throw cast_error("Unable to represent system_clock in local time");
|
||||
}
|
||||
return PyDateTime_FromDateAndTime(localtime.tm_year + 1900,
|
||||
localtime.tm_mon + 1,
|
||||
localtime.tm_mday,
|
||||
@ -173,19 +207,19 @@ public:
|
||||
localtime.tm_sec,
|
||||
us.count());
|
||||
}
|
||||
PYBIND11_TYPE_CASTER(type, _("datetime.datetime"));
|
||||
PYBIND11_TYPE_CASTER(type, const_name("datetime.datetime"));
|
||||
};
|
||||
|
||||
// Other clocks that are not the system clock are not measured as datetime.datetime objects
|
||||
// since they are not measured on calendar time. So instead we just make them timedeltas
|
||||
// Or if they have passed us a time as a float we convert that
|
||||
template <typename Clock, typename Duration> class type_caster<std::chrono::time_point<Clock, Duration>>
|
||||
: public duration_caster<std::chrono::time_point<Clock, Duration>> {
|
||||
};
|
||||
template <typename Clock, typename Duration>
|
||||
class type_caster<std::chrono::time_point<Clock, Duration>>
|
||||
: public duration_caster<std::chrono::time_point<Clock, Duration>> {};
|
||||
|
||||
template <typename Rep, typename Period> class type_caster<std::chrono::duration<Rep, Period>>
|
||||
: public duration_caster<std::chrono::duration<Rep, Period>> {
|
||||
};
|
||||
template <typename Rep, typename Period>
|
||||
class type_caster<std::chrono::duration<Rep, Period>>
|
||||
: public duration_caster<std::chrono::duration<Rep, Period>> {};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
31
3rdparty/pybind11/include/pybind11/complex.h
vendored
31
3rdparty/pybind11/include/pybind11/complex.h
vendored
@ -10,42 +10,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#include <complex>
|
||||
|
||||
/// glibc defines I as a macro which breaks things, e.g., boost template names
|
||||
#ifdef I
|
||||
# undef I
|
||||
# undef I
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
template <typename T> struct format_descriptor<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
||||
template <typename T>
|
||||
struct format_descriptor<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
||||
static constexpr const char c = format_descriptor<T>::c;
|
||||
static constexpr const char value[3] = { 'Z', c, '\0' };
|
||||
static constexpr const char value[3] = {'Z', c, '\0'};
|
||||
static std::string format() { return std::string(value); }
|
||||
};
|
||||
|
||||
#ifndef PYBIND11_CPP17
|
||||
|
||||
template <typename T> constexpr const char format_descriptor<
|
||||
std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>>::value[3];
|
||||
template <typename T>
|
||||
constexpr const char
|
||||
format_descriptor<std::complex<T>,
|
||||
detail::enable_if_t<std::is_floating_point<T>::value>>::value[3];
|
||||
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
template <typename T> struct is_fmt_numeric<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
||||
template <typename T>
|
||||
struct is_fmt_numeric<std::complex<T>, detail::enable_if_t<std::is_floating_point<T>::value>> {
|
||||
static constexpr bool value = true;
|
||||
static constexpr int index = is_fmt_numeric<T>::index + 3;
|
||||
};
|
||||
|
||||
template <typename T> class type_caster<std::complex<T>> {
|
||||
template <typename T>
|
||||
class type_caster<std::complex<T>> {
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!src)
|
||||
if (!src) {
|
||||
return false;
|
||||
if (!convert && !PyComplex_Check(src.ptr()))
|
||||
}
|
||||
if (!convert && !PyComplex_Check(src.ptr())) {
|
||||
return false;
|
||||
}
|
||||
Py_complex result = PyComplex_AsCComplex(src.ptr());
|
||||
if (result.real == -1.0 && PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
@ -55,11 +63,12 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
static handle cast(const std::complex<T> &src, return_value_policy /* policy */, handle /* parent */) {
|
||||
static handle
|
||||
cast(const std::complex<T> &src, return_value_policy /* policy */, handle /* parent */) {
|
||||
return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(std::complex<T>, _("complex"));
|
||||
PYBIND11_TYPE_CASTER(std::complex<T>, const_name("complex"));
|
||||
};
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
331
3rdparty/pybind11/include/pybind11/detail/class.h
vendored
331
3rdparty/pybind11/include/pybind11/detail/class.h
vendored
@ -15,13 +15,14 @@
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
#if PY_VERSION_HEX >= 0x03030000 && !defined(PYPY_VERSION)
|
||||
# define PYBIND11_BUILTIN_QUALNAME
|
||||
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
|
||||
#if !defined(PYPY_VERSION)
|
||||
# define PYBIND11_BUILTIN_QUALNAME
|
||||
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
|
||||
#else
|
||||
// In pre-3.3 Python, we still set __qualname__ so that we can produce reliable function type
|
||||
// signatures; in 3.3+ this macro expands to nothing:
|
||||
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) setattr((PyObject *) obj, "__qualname__", nameobj)
|
||||
// In PyPy, we still set __qualname__ so that we can produce reliable function type
|
||||
// signatures; in CPython this macro expands to nothing:
|
||||
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) \
|
||||
setattr((PyObject *) obj, "__qualname__", nameobj)
|
||||
#endif
|
||||
|
||||
inline std::string get_fully_qualified_tp_name(PyTypeObject *type) {
|
||||
@ -65,24 +66,26 @@ inline PyTypeObject *make_static_property_type() {
|
||||
issue no Python C API calls which could potentially invoke the
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||
if (!heap_type)
|
||||
auto *heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||
if (!heap_type) {
|
||||
pybind11_fail("make_static_property_type(): error allocating type!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
# ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
heap_type->ht_qualname = name_obj.inc_ref().ptr();
|
||||
#endif
|
||||
# endif
|
||||
|
||||
auto type = &heap_type->ht_type;
|
||||
auto *type = &heap_type->ht_type;
|
||||
type->tp_name = name;
|
||||
type->tp_base = type_incref(&PyProperty_Type);
|
||||
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
|
||||
type->tp_descr_get = pybind11_static_get;
|
||||
type->tp_descr_set = pybind11_static_set;
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail("make_static_property_type(): failure in PyType_Ready()!");
|
||||
}
|
||||
|
||||
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||
@ -98,15 +101,17 @@ inline PyTypeObject *make_static_property_type() {
|
||||
inline PyTypeObject *make_static_property_type() {
|
||||
auto d = dict();
|
||||
PyObject *result = PyRun_String(R"(\
|
||||
class pybind11_static_property(property):
|
||||
def __get__(self, obj, cls):
|
||||
return property.__get__(self, cls, cls)
|
||||
class pybind11_static_property(property):
|
||||
def __get__(self, obj, cls):
|
||||
return property.__get__(self, cls, cls)
|
||||
|
||||
def __set__(self, obj, value):
|
||||
cls = obj if isinstance(obj, type) else type(obj)
|
||||
property.__set__(self, cls, value)
|
||||
)", Py_file_input, d.ptr(), d.ptr()
|
||||
);
|
||||
def __set__(self, obj, value):
|
||||
cls = obj if isinstance(obj, type) else type(obj)
|
||||
property.__set__(self, cls, value)
|
||||
)",
|
||||
Py_file_input,
|
||||
d.ptr(),
|
||||
d.ptr());
|
||||
if (result == nullptr)
|
||||
throw error_already_set();
|
||||
Py_DECREF(result);
|
||||
@ -119,7 +124,7 @@ inline PyTypeObject *make_static_property_type() {
|
||||
By default, Python replaces the `static_property` itself, but for wrapped C++ types
|
||||
we need to call `static_property.__set__()` in order to propagate the new value to
|
||||
the underlying C++ data structure. */
|
||||
extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyObject* value) {
|
||||
extern "C" inline int pybind11_meta_setattro(PyObject *obj, PyObject *name, PyObject *value) {
|
||||
// Use `_PyType_Lookup()` instead of `PyObject_GetAttr()` in order to get the raw
|
||||
// descriptor (`property`) instead of calling `tp_descr_get` (`property.__get__()`).
|
||||
PyObject *descr = _PyType_Lookup((PyTypeObject *) obj, name);
|
||||
@ -128,9 +133,10 @@ extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyOb
|
||||
// 1. `Type.static_prop = value` --> descr_set: `Type.static_prop.__set__(value)`
|
||||
// 2. `Type.static_prop = other_static_prop` --> setattro: replace existing `static_prop`
|
||||
// 3. `Type.regular_attribute = value` --> setattro: regular attribute assignment
|
||||
const auto static_prop = (PyObject *) get_internals().static_property_type;
|
||||
const auto call_descr_set = descr && value && PyObject_IsInstance(descr, static_prop)
|
||||
&& !PyObject_IsInstance(value, static_prop);
|
||||
auto *const static_prop = (PyObject *) get_internals().static_property_type;
|
||||
const auto call_descr_set = (descr != nullptr) && (value != nullptr)
|
||||
&& (PyObject_IsInstance(descr, static_prop) != 0)
|
||||
&& (PyObject_IsInstance(value, static_prop) == 0);
|
||||
if (call_descr_set) {
|
||||
// Call `static_property.__set__()` instead of replacing the `static_property`.
|
||||
#if !defined(PYPY_VERSION)
|
||||
@ -149,7 +155,6 @@ extern "C" inline int pybind11_meta_setattro(PyObject* obj, PyObject* name, PyOb
|
||||
}
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
/**
|
||||
* Python 3's PyInstanceMethod_Type hides itself via its tp_descr_get, which prevents aliasing
|
||||
* methods via cls.attr("m2") = cls.attr("m1"): instead the tp_descr_get returns a plain function,
|
||||
@ -162,11 +167,8 @@ extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name
|
||||
Py_INCREF(descr);
|
||||
return descr;
|
||||
}
|
||||
else {
|
||||
return PyType_Type.tp_getattro(obj, name);
|
||||
}
|
||||
return PyType_Type.tp_getattro(obj, name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/// metaclass `__call__` function that is used to create all pybind11 objects.
|
||||
extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, PyObject *kwargs) {
|
||||
@ -178,12 +180,13 @@ extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, P
|
||||
}
|
||||
|
||||
// This must be a pybind11 instance
|
||||
auto instance = reinterpret_cast<detail::instance *>(self);
|
||||
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||
|
||||
// Ensure that the base __init__ function(s) were called
|
||||
for (const auto &vh : values_and_holders(instance)) {
|
||||
if (!vh.holder_constructed()) {
|
||||
PyErr_Format(PyExc_TypeError, "%.200s.__init__() must be called when overriding __init__",
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s.__init__() must be called when overriding __init__",
|
||||
get_fully_qualified_tp_name(vh.type->type).c_str());
|
||||
Py_DECREF(self);
|
||||
return nullptr;
|
||||
@ -202,27 +205,28 @@ extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
|
||||
// 1) be found in internals.registered_types_py
|
||||
// 2) have exactly one associated `detail::type_info`
|
||||
auto found_type = internals.registered_types_py.find(type);
|
||||
if (found_type != internals.registered_types_py.end() &&
|
||||
found_type->second.size() == 1 &&
|
||||
found_type->second[0]->type == type) {
|
||||
if (found_type != internals.registered_types_py.end() && found_type->second.size() == 1
|
||||
&& found_type->second[0]->type == type) {
|
||||
|
||||
auto *tinfo = found_type->second[0];
|
||||
auto tindex = std::type_index(*tinfo->cpptype);
|
||||
internals.direct_conversions.erase(tindex);
|
||||
|
||||
if (tinfo->module_local)
|
||||
registered_local_types_cpp().erase(tindex);
|
||||
else
|
||||
if (tinfo->module_local) {
|
||||
get_local_internals().registered_types_cpp.erase(tindex);
|
||||
} else {
|
||||
internals.registered_types_cpp.erase(tindex);
|
||||
}
|
||||
internals.registered_types_py.erase(tinfo->type);
|
||||
|
||||
// Actually just `std::erase_if`, but that's only available in C++20
|
||||
auto &cache = internals.inactive_override_cache;
|
||||
for (auto it = cache.begin(), last = cache.end(); it != last; ) {
|
||||
if (it->first == (PyObject *) tinfo->type)
|
||||
for (auto it = cache.begin(), last = cache.end(); it != last;) {
|
||||
if (it->first == (PyObject *) tinfo->type) {
|
||||
it = cache.erase(it);
|
||||
else
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
delete tinfo;
|
||||
@ -234,7 +238,7 @@ extern "C" inline void pybind11_meta_dealloc(PyObject *obj) {
|
||||
/** This metaclass is assigned by default to all pybind11 types and is required in order
|
||||
for static properties to function correctly. Users may override this using `py::metaclass`.
|
||||
Return value: New reference. */
|
||||
inline PyTypeObject* make_default_metaclass() {
|
||||
inline PyTypeObject *make_default_metaclass() {
|
||||
constexpr auto *name = "pybind11_type";
|
||||
auto name_obj = reinterpret_steal<object>(PYBIND11_FROM_STRING(name));
|
||||
|
||||
@ -242,16 +246,17 @@ inline PyTypeObject* make_default_metaclass() {
|
||||
issue no Python C API calls which could potentially invoke the
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||
if (!heap_type)
|
||||
auto *heap_type = (PyHeapTypeObject *) PyType_Type.tp_alloc(&PyType_Type, 0);
|
||||
if (!heap_type) {
|
||||
pybind11_fail("make_default_metaclass(): error allocating metaclass!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
heap_type->ht_qualname = name_obj.inc_ref().ptr();
|
||||
#endif
|
||||
|
||||
auto type = &heap_type->ht_type;
|
||||
auto *type = &heap_type->ht_type;
|
||||
type->tp_name = name;
|
||||
type->tp_base = type_incref(&PyType_Type);
|
||||
type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HEAPTYPE;
|
||||
@ -259,14 +264,13 @@ inline PyTypeObject* make_default_metaclass() {
|
||||
type->tp_call = pybind11_meta_call;
|
||||
|
||||
type->tp_setattro = pybind11_meta_setattro;
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
type->tp_getattro = pybind11_meta_getattro;
|
||||
#endif
|
||||
|
||||
type->tp_dealloc = pybind11_meta_dealloc;
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail("make_default_metaclass(): failure in PyType_Ready()!");
|
||||
}
|
||||
|
||||
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||
@ -276,16 +280,20 @@ inline PyTypeObject* make_default_metaclass() {
|
||||
|
||||
/// For multiple inheritance types we need to recursively register/deregister base pointers for any
|
||||
/// base classes with pointers that are difference from the instance value pointer so that we can
|
||||
/// correctly recognize an offset base class pointer. This calls a function with any offset base ptrs.
|
||||
inline void traverse_offset_bases(void *valueptr, const detail::type_info *tinfo, instance *self,
|
||||
bool (*f)(void * /*parentptr*/, instance * /*self*/)) {
|
||||
/// correctly recognize an offset base class pointer. This calls a function with any offset base
|
||||
/// ptrs.
|
||||
inline void traverse_offset_bases(void *valueptr,
|
||||
const detail::type_info *tinfo,
|
||||
instance *self,
|
||||
bool (*f)(void * /*parentptr*/, instance * /*self*/)) {
|
||||
for (handle h : reinterpret_borrow<tuple>(tinfo->type->tp_bases)) {
|
||||
if (auto parent_tinfo = get_type_info((PyTypeObject *) h.ptr())) {
|
||||
if (auto *parent_tinfo = get_type_info((PyTypeObject *) h.ptr())) {
|
||||
for (auto &c : parent_tinfo->implicit_casts) {
|
||||
if (c.first == tinfo->cpptype) {
|
||||
auto *parentptr = c.second(valueptr);
|
||||
if (parentptr != valueptr)
|
||||
if (parentptr != valueptr) {
|
||||
f(parentptr, self);
|
||||
}
|
||||
traverse_offset_bases(parentptr, parent_tinfo, self, f);
|
||||
break;
|
||||
}
|
||||
@ -312,36 +320,36 @@ inline bool deregister_instance_impl(void *ptr, instance *self) {
|
||||
|
||||
inline void register_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||
register_instance_impl(valptr, self);
|
||||
if (!tinfo->simple_ancestors)
|
||||
if (!tinfo->simple_ancestors) {
|
||||
traverse_offset_bases(valptr, tinfo, self, register_instance_impl);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo) {
|
||||
bool ret = deregister_instance_impl(valptr, self);
|
||||
if (!tinfo->simple_ancestors)
|
||||
if (!tinfo->simple_ancestors) {
|
||||
traverse_offset_bases(valptr, tinfo, self, deregister_instance_impl);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Instance creation function for all pybind11 types. It allocates the internal instance layout for
|
||||
/// holding C++ objects and holders. Allocation is done lazily (the first time the instance is cast
|
||||
/// to a reference or pointer), and initialization is done by an `__init__` function.
|
||||
/// Instance creation function for all pybind11 types. It allocates the internal instance layout
|
||||
/// for holding C++ objects and holders. Allocation is done lazily (the first time the instance is
|
||||
/// cast to a reference or pointer), and initialization is done by an `__init__` function.
|
||||
inline PyObject *make_new_instance(PyTypeObject *type) {
|
||||
#if defined(PYPY_VERSION)
|
||||
// PyPy gets tp_basicsize wrong (issue 2482) under multiple inheritance when the first inherited
|
||||
// object is a a plain Python type (i.e. not derived from an extension type). Fix it.
|
||||
// PyPy gets tp_basicsize wrong (issue 2482) under multiple inheritance when the first
|
||||
// inherited object is a plain Python type (i.e. not derived from an extension type). Fix it.
|
||||
ssize_t instance_size = static_cast<ssize_t>(sizeof(instance));
|
||||
if (type->tp_basicsize < instance_size) {
|
||||
type->tp_basicsize = instance_size;
|
||||
}
|
||||
#endif
|
||||
PyObject *self = type->tp_alloc(type, 0);
|
||||
auto inst = reinterpret_cast<instance *>(self);
|
||||
auto *inst = reinterpret_cast<instance *>(self);
|
||||
// Allocate the value/holder internals:
|
||||
inst->allocate_layout();
|
||||
|
||||
inst->owned = true;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -363,14 +371,14 @@ 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);
|
||||
auto *instance = reinterpret_cast<detail::instance *>(nurse);
|
||||
instance->has_patients = true;
|
||||
Py_INCREF(patient);
|
||||
internals.patients[nurse].push_back(patient);
|
||||
}
|
||||
|
||||
inline void clear_patients(PyObject *self) {
|
||||
auto instance = reinterpret_cast<detail::instance *>(self);
|
||||
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||
auto &internals = get_internals();
|
||||
auto pos = internals.patients.find(self);
|
||||
assert(pos != internals.patients.end());
|
||||
@ -380,14 +388,15 @@ inline void clear_patients(PyObject *self) {
|
||||
auto patients = std::move(pos->second);
|
||||
internals.patients.erase(pos);
|
||||
instance->has_patients = false;
|
||||
for (PyObject *&patient : patients)
|
||||
for (PyObject *&patient : patients) {
|
||||
Py_CLEAR(patient);
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears all internal data from the instance and removes it from registered instances in
|
||||
/// preparation for deallocation.
|
||||
inline void clear_instance(PyObject *self) {
|
||||
auto instance = reinterpret_cast<detail::instance *>(self);
|
||||
auto *instance = reinterpret_cast<detail::instance *>(self);
|
||||
|
||||
// Deallocate any values/holders, if present:
|
||||
for (auto &v_h : values_and_holders(instance)) {
|
||||
@ -395,25 +404,32 @@ inline void clear_instance(PyObject *self) {
|
||||
|
||||
// We have to deregister before we call dealloc because, for virtual MI types, we still
|
||||
// need to be able to get the parent pointers.
|
||||
if (v_h.instance_registered() && !deregister_instance(instance, v_h.value_ptr(), v_h.type))
|
||||
pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||
if (v_h.instance_registered()
|
||||
&& !deregister_instance(instance, v_h.value_ptr(), v_h.type)) {
|
||||
pybind11_fail(
|
||||
"pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
|
||||
}
|
||||
|
||||
if (instance->owned || v_h.holder_constructed())
|
||||
if (instance->owned || v_h.holder_constructed()) {
|
||||
v_h.type->dealloc(v_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Deallocate the value/holder layout internals:
|
||||
instance->deallocate_layout();
|
||||
|
||||
if (instance->weakrefs)
|
||||
if (instance->weakrefs) {
|
||||
PyObject_ClearWeakRefs(self);
|
||||
}
|
||||
|
||||
PyObject **dict_ptr = _PyObject_GetDictPtr(self);
|
||||
if (dict_ptr)
|
||||
if (dict_ptr) {
|
||||
Py_CLEAR(*dict_ptr);
|
||||
}
|
||||
|
||||
if (instance->has_patients)
|
||||
if (instance->has_patients) {
|
||||
clear_patients(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Instance destructor function for all pybind11 types. It calls `type_info.dealloc`
|
||||
@ -421,7 +437,7 @@ inline void clear_instance(PyObject *self) {
|
||||
extern "C" inline void pybind11_object_dealloc(PyObject *self) {
|
||||
clear_instance(self);
|
||||
|
||||
auto type = Py_TYPE(self);
|
||||
auto *type = Py_TYPE(self);
|
||||
type->tp_free(self);
|
||||
|
||||
#if PY_VERSION_HEX < 0x03080000
|
||||
@ -439,6 +455,8 @@ extern "C" inline void pybind11_object_dealloc(PyObject *self) {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string error_string();
|
||||
|
||||
/** Create the type which can be used as a common base for all classes. This is
|
||||
needed in order to satisfy Python's requirements for multiple inheritance.
|
||||
Return value: New reference. */
|
||||
@ -450,16 +468,17 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||
issue no Python C API calls which could potentially invoke the
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||
if (!heap_type)
|
||||
auto *heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||
if (!heap_type) {
|
||||
pybind11_fail("make_object_base_type(): error allocating type!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name_obj.inc_ref().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
heap_type->ht_qualname = name_obj.inc_ref().ptr();
|
||||
#endif
|
||||
|
||||
auto type = &heap_type->ht_type;
|
||||
auto *type = &heap_type->ht_type;
|
||||
type->tp_name = name;
|
||||
type->tp_base = type_incref(&PyBaseObject_Type);
|
||||
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
|
||||
@ -472,8 +491,9 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||
/* Support weak references (needed for the keep_alive feature) */
|
||||
type->tp_weaklistoffset = offsetof(instance, weakrefs);
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
pybind11_fail("PyType_Ready failed in make_object_base_type():" + error_string());
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail("PyType_Ready failed in make_object_base_type(): " + error_string());
|
||||
}
|
||||
|
||||
setattr((PyObject *) type, "__module__", str("pybind11_builtins"));
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, name_obj);
|
||||
@ -482,33 +502,14 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass) {
|
||||
return (PyObject *) heap_type;
|
||||
}
|
||||
|
||||
/// dynamic_attr: Support for `d = instance.__dict__`.
|
||||
extern "C" inline PyObject *pybind11_get_dict(PyObject *self, void *) {
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(self);
|
||||
if (!dict)
|
||||
dict = PyDict_New();
|
||||
Py_XINCREF(dict);
|
||||
return dict;
|
||||
}
|
||||
|
||||
/// dynamic_attr: Support for `instance.__dict__ = dict()`.
|
||||
extern "C" inline int pybind11_set_dict(PyObject *self, PyObject *new_dict, void *) {
|
||||
if (!PyDict_Check(new_dict)) {
|
||||
PyErr_Format(PyExc_TypeError, "__dict__ must be set to a dictionary, not a '%.200s'",
|
||||
get_fully_qualified_tp_name(Py_TYPE(new_dict)).c_str());
|
||||
return -1;
|
||||
}
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(self);
|
||||
Py_INCREF(new_dict);
|
||||
Py_CLEAR(dict);
|
||||
dict = new_dict;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// dynamic_attr: Allow the garbage collector to traverse the internal instance `__dict__`.
|
||||
extern "C" inline int pybind11_traverse(PyObject *self, visitproc visit, void *arg) {
|
||||
PyObject *&dict = *_PyObject_GetDictPtr(self);
|
||||
Py_VISIT(dict);
|
||||
// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
|
||||
#if PY_VERSION_HEX >= 0x03090000
|
||||
Py_VISIT(Py_TYPE(self));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -521,17 +522,28 @@ extern "C" inline int pybind11_clear(PyObject *self) {
|
||||
|
||||
/// Give instances of this type a `__dict__` and opt into garbage collection.
|
||||
inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
|
||||
auto type = &heap_type->ht_type;
|
||||
auto *type = &heap_type->ht_type;
|
||||
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
|
||||
type->tp_dictoffset = type->tp_basicsize; // place dict at the end
|
||||
type->tp_basicsize += (ssize_t)sizeof(PyObject *); // and allocate enough space for it
|
||||
#if PY_VERSION_HEX < 0x030B0000
|
||||
type->tp_dictoffset = type->tp_basicsize; // place dict at the end
|
||||
type->tp_basicsize += (ssize_t) sizeof(PyObject *); // and allocate enough space for it
|
||||
#else
|
||||
type->tp_flags |= Py_TPFLAGS_MANAGED_DICT;
|
||||
#endif
|
||||
type->tp_traverse = pybind11_traverse;
|
||||
type->tp_clear = pybind11_clear;
|
||||
|
||||
static PyGetSetDef getset[] = {
|
||||
{const_cast<char*>("__dict__"), pybind11_get_dict, pybind11_set_dict, nullptr, nullptr},
|
||||
{nullptr, nullptr, nullptr, nullptr, nullptr}
|
||||
};
|
||||
static PyGetSetDef getset[] = {{
|
||||
#if PY_VERSION_HEX < 0x03070000
|
||||
const_cast<char *>("__dict__"),
|
||||
#else
|
||||
"__dict__",
|
||||
#endif
|
||||
PyObject_GenericGetDict,
|
||||
PyObject_GenericSetDict,
|
||||
nullptr,
|
||||
nullptr},
|
||||
{nullptr, nullptr, nullptr, nullptr, nullptr}};
|
||||
type->tp_getset = getset;
|
||||
}
|
||||
|
||||
@ -541,38 +553,42 @@ extern "C" inline int pybind11_getbuffer(PyObject *obj, Py_buffer *view, int fla
|
||||
type_info *tinfo = nullptr;
|
||||
for (auto type : reinterpret_borrow<tuple>(Py_TYPE(obj)->tp_mro)) {
|
||||
tinfo = get_type_info((PyTypeObject *) type.ptr());
|
||||
if (tinfo && tinfo->get_buffer)
|
||||
if (tinfo && tinfo->get_buffer) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (view == nullptr || !tinfo || !tinfo->get_buffer) {
|
||||
if (view)
|
||||
if (view) {
|
||||
view->obj = nullptr;
|
||||
}
|
||||
PyErr_SetString(PyExc_BufferError, "pybind11_getbuffer(): Internal error");
|
||||
return -1;
|
||||
}
|
||||
std::memset(view, 0, sizeof(Py_buffer));
|
||||
buffer_info *info = tinfo->get_buffer(obj, tinfo->get_buffer_data);
|
||||
if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) {
|
||||
delete info;
|
||||
// view->obj = nullptr; // Was just memset to 0, so not necessary
|
||||
PyErr_SetString(PyExc_BufferError, "Writable buffer requested for readonly storage");
|
||||
return -1;
|
||||
}
|
||||
view->obj = obj;
|
||||
view->ndim = 1;
|
||||
view->internal = info;
|
||||
view->buf = info->ptr;
|
||||
view->itemsize = info->itemsize;
|
||||
view->len = view->itemsize;
|
||||
for (auto s : info->shape)
|
||||
for (auto s : info->shape) {
|
||||
view->len *= s;
|
||||
view->readonly = info->readonly;
|
||||
if ((flags & PyBUF_WRITABLE) == PyBUF_WRITABLE && info->readonly) {
|
||||
if (view)
|
||||
view->obj = nullptr;
|
||||
PyErr_SetString(PyExc_BufferError, "Writable buffer requested for readonly storage");
|
||||
return -1;
|
||||
}
|
||||
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT)
|
||||
view->readonly = static_cast<int>(info->readonly);
|
||||
if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) {
|
||||
view->format = const_cast<char *>(info->format.c_str());
|
||||
}
|
||||
if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) {
|
||||
view->ndim = (int) info->ndim;
|
||||
view->strides = &info->strides[0];
|
||||
view->shape = &info->shape[0];
|
||||
view->strides = info->strides.data();
|
||||
view->shape = info->shape.data();
|
||||
}
|
||||
Py_INCREF(view->obj);
|
||||
return 0;
|
||||
@ -586,9 +602,6 @@ extern "C" inline void pybind11_releasebuffer(PyObject *, Py_buffer *view) {
|
||||
/// Give this type a buffer interface.
|
||||
inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) {
|
||||
heap_type->ht_type.tp_as_buffer = &heap_type->as_buffer;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
heap_type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
|
||||
#endif
|
||||
|
||||
heap_type->as_buffer.bf_getbuffer = pybind11_getbuffer;
|
||||
heap_type->as_buffer.bf_releasebuffer = pybind11_releasebuffer;
|
||||
@ -596,70 +609,68 @@ inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) {
|
||||
|
||||
/** Create a brand new Python type according to the `type_record` specification.
|
||||
Return value: New reference. */
|
||||
inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
inline PyObject *make_new_python_type(const type_record &rec) {
|
||||
auto name = reinterpret_steal<object>(PYBIND11_FROM_STRING(rec.name));
|
||||
|
||||
auto qualname = name;
|
||||
if (rec.scope && !PyModule_Check(rec.scope.ptr()) && hasattr(rec.scope, "__qualname__")) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
qualname = reinterpret_steal<object>(
|
||||
PyUnicode_FromFormat("%U.%U", rec.scope.attr("__qualname__").ptr(), name.ptr()));
|
||||
#else
|
||||
qualname = str(rec.scope.attr("__qualname__").cast<std::string>() + "." + rec.name);
|
||||
#endif
|
||||
}
|
||||
|
||||
object module_;
|
||||
if (rec.scope) {
|
||||
if (hasattr(rec.scope, "__module__"))
|
||||
if (hasattr(rec.scope, "__module__")) {
|
||||
module_ = rec.scope.attr("__module__");
|
||||
else if (hasattr(rec.scope, "__name__"))
|
||||
} else if (hasattr(rec.scope, "__name__")) {
|
||||
module_ = rec.scope.attr("__name__");
|
||||
}
|
||||
}
|
||||
|
||||
auto full_name = c_str(
|
||||
const auto *full_name = c_str(
|
||||
#if !defined(PYPY_VERSION)
|
||||
module_ ? str(module_).cast<std::string>() + "." + rec.name :
|
||||
#endif
|
||||
rec.name);
|
||||
rec.name);
|
||||
|
||||
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) */
|
||||
size_t size = strlen(rec.doc) + 1;
|
||||
size_t size = std::strlen(rec.doc) + 1;
|
||||
tp_doc = (char *) PyObject_MALLOC(size);
|
||||
memcpy((void *) tp_doc, rec.doc, size);
|
||||
std::memcpy((void *) tp_doc, rec.doc, size);
|
||||
}
|
||||
|
||||
auto &internals = get_internals();
|
||||
auto bases = tuple(rec.bases);
|
||||
auto base = (bases.empty()) ? internals.instance_base
|
||||
: bases[0].ptr();
|
||||
auto *base = (bases.empty()) ? internals.instance_base : bases[0].ptr();
|
||||
|
||||
/* Danger zone: from now (and until PyType_Ready), make sure to
|
||||
issue no Python C API calls which could potentially invoke the
|
||||
garbage collector (the GC will call type_traverse(), which will in
|
||||
turn find the newly constructed type in an invalid state) */
|
||||
auto metaclass = rec.metaclass.ptr() ? (PyTypeObject *) rec.metaclass.ptr()
|
||||
: internals.default_metaclass;
|
||||
auto *metaclass
|
||||
= rec.metaclass.ptr() ? (PyTypeObject *) rec.metaclass.ptr() : internals.default_metaclass;
|
||||
|
||||
auto heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||
if (!heap_type)
|
||||
auto *heap_type = (PyHeapTypeObject *) metaclass->tp_alloc(metaclass, 0);
|
||||
if (!heap_type) {
|
||||
pybind11_fail(std::string(rec.name) + ": Unable to create type object!");
|
||||
}
|
||||
|
||||
heap_type->ht_name = name.release().ptr();
|
||||
#ifdef PYBIND11_BUILTIN_QUALNAME
|
||||
heap_type->ht_qualname = qualname.inc_ref().ptr();
|
||||
#endif
|
||||
|
||||
auto type = &heap_type->ht_type;
|
||||
auto *type = &heap_type->ht_type;
|
||||
type->tp_name = full_name;
|
||||
type->tp_doc = tp_doc;
|
||||
type->tp_base = type_incref((PyTypeObject *)base);
|
||||
type->tp_base = type_incref((PyTypeObject *) base);
|
||||
type->tp_basicsize = static_cast<ssize_t>(sizeof(instance));
|
||||
if (!bases.empty())
|
||||
if (!bases.empty()) {
|
||||
type->tp_bases = bases.release().ptr();
|
||||
}
|
||||
|
||||
/* Don't inherit base __init__ */
|
||||
type->tp_init = pybind11_object_init;
|
||||
@ -668,38 +679,42 @@ inline PyObject* make_new_python_type(const type_record &rec) {
|
||||
type->tp_as_number = &heap_type->as_number;
|
||||
type->tp_as_sequence = &heap_type->as_sequence;
|
||||
type->tp_as_mapping = &heap_type->as_mapping;
|
||||
#if PY_VERSION_HEX >= 0x03050000
|
||||
type->tp_as_async = &heap_type->as_async;
|
||||
#endif
|
||||
|
||||
/* Flags */
|
||||
type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
|
||||
#endif
|
||||
if (!rec.is_final)
|
||||
if (!rec.is_final) {
|
||||
type->tp_flags |= Py_TPFLAGS_BASETYPE;
|
||||
}
|
||||
|
||||
if (rec.dynamic_attr)
|
||||
if (rec.dynamic_attr) {
|
||||
enable_dynamic_attributes(heap_type);
|
||||
}
|
||||
|
||||
if (rec.buffer_protocol)
|
||||
if (rec.buffer_protocol) {
|
||||
enable_buffer_protocol(heap_type);
|
||||
}
|
||||
|
||||
if (PyType_Ready(type) < 0)
|
||||
pybind11_fail(std::string(rec.name) + ": PyType_Ready failed (" + error_string() + ")!");
|
||||
if (rec.custom_type_setup_callback) {
|
||||
rec.custom_type_setup_callback(heap_type);
|
||||
}
|
||||
|
||||
assert(rec.dynamic_attr ? PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC)
|
||||
: !PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||
if (PyType_Ready(type) < 0) {
|
||||
pybind11_fail(std::string(rec.name) + ": PyType_Ready failed: " + error_string());
|
||||
}
|
||||
|
||||
assert(!rec.dynamic_attr || PyType_HasFeature(type, Py_TPFLAGS_HAVE_GC));
|
||||
|
||||
/* Register type with the parent scope */
|
||||
if (rec.scope)
|
||||
if (rec.scope) {
|
||||
setattr(rec.scope, rec.name, (PyObject *) type);
|
||||
else
|
||||
} else {
|
||||
Py_INCREF(type); // Keep it alive forever (reference leak)
|
||||
}
|
||||
|
||||
if (module_) // Needed by pydoc
|
||||
if (module_) { // Needed by pydoc
|
||||
setattr((PyObject *) type, "__module__", module_);
|
||||
}
|
||||
|
||||
PYBIND11_SET_OLDPY_QUALNAME(type, qualname);
|
||||
|
||||
|
1026
3rdparty/pybind11/include/pybind11/detail/common.h
vendored
1026
3rdparty/pybind11/include/pybind11/detail/common.h
vendored
File diff suppressed because it is too large
Load Diff
108
3rdparty/pybind11/include/pybind11/detail/descr.h
vendored
108
3rdparty/pybind11/include/pybind11/detail/descr.h
vendored
@ -15,24 +15,26 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
# define PYBIND11_DESCR_CONSTEXPR static constexpr
|
||||
# define PYBIND11_DESCR_CONSTEXPR static constexpr
|
||||
#else
|
||||
# define PYBIND11_DESCR_CONSTEXPR const
|
||||
# define PYBIND11_DESCR_CONSTEXPR const
|
||||
#endif
|
||||
|
||||
/* Concatenate type signatures at compile time */
|
||||
template <size_t N, typename... Ts>
|
||||
struct descr {
|
||||
char text[N + 1];
|
||||
char text[N + 1]{'\0'};
|
||||
|
||||
constexpr descr() : text{'\0'} { }
|
||||
constexpr descr(char const (&s)[N+1]) : descr(s, make_index_sequence<N>()) { }
|
||||
constexpr descr() = default;
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr descr(char const (&s)[N + 1]) : descr(s, make_index_sequence<N>()) {}
|
||||
|
||||
template <size_t... Is>
|
||||
constexpr descr(char const (&s)[N+1], index_sequence<Is...>) : text{s[Is]..., '\0'} { }
|
||||
constexpr descr(char const (&s)[N + 1], index_sequence<Is...>) : text{s[Is]..., '\0'} {}
|
||||
|
||||
template <typename... Chars>
|
||||
constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} { }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
constexpr descr(char c, Chars... cs) : text{c, static_cast<char>(cs)..., '\0'} {}
|
||||
|
||||
static constexpr std::array<const std::type_info *, sizeof...(Ts) + 1> types() {
|
||||
return {{&typeid(Ts)..., nullptr}};
|
||||
@ -40,60 +42,116 @@ struct descr {
|
||||
};
|
||||
|
||||
template <size_t N1, size_t N2, typename... Ts1, typename... Ts2, size_t... Is1, size_t... Is2>
|
||||
constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b,
|
||||
index_sequence<Is1...>, index_sequence<Is2...>) {
|
||||
constexpr descr<N1 + N2, Ts1..., Ts2...> plus_impl(const descr<N1, Ts1...> &a,
|
||||
const descr<N2, Ts2...> &b,
|
||||
index_sequence<Is1...>,
|
||||
index_sequence<Is2...>) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(b);
|
||||
return {a.text[Is1]..., b.text[Is2]...};
|
||||
}
|
||||
|
||||
template <size_t N1, size_t N2, typename... Ts1, typename... Ts2>
|
||||
constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a, const descr<N2, Ts2...> &b) {
|
||||
constexpr descr<N1 + N2, Ts1..., Ts2...> operator+(const descr<N1, Ts1...> &a,
|
||||
const descr<N2, Ts2...> &b) {
|
||||
return plus_impl(a, b, make_index_sequence<N1>(), make_index_sequence<N2>());
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
constexpr descr<N - 1> _(char const(&text)[N]) { return descr<N - 1>(text); }
|
||||
constexpr descr<0> _(char const(&)[1]) { return {}; }
|
||||
constexpr descr<N - 1> const_name(char const (&text)[N]) {
|
||||
return descr<N - 1>(text);
|
||||
}
|
||||
constexpr descr<0> const_name(char const (&)[1]) { return {}; }
|
||||
|
||||
template <size_t Rem, size_t... Digits> struct int_to_str : int_to_str<Rem/10, Rem%10, Digits...> { };
|
||||
template <size_t...Digits> struct int_to_str<0, Digits...> {
|
||||
template <size_t Rem, size_t... Digits>
|
||||
struct int_to_str : int_to_str<Rem / 10, Rem % 10, Digits...> {};
|
||||
template <size_t... Digits>
|
||||
struct int_to_str<0, Digits...> {
|
||||
// WARNING: This only works with C++17 or higher.
|
||||
static constexpr auto digits = descr<sizeof...(Digits)>(('0' + Digits)...);
|
||||
};
|
||||
|
||||
// Ternary description (like std::conditional)
|
||||
template <bool B, size_t N1, size_t N2>
|
||||
constexpr enable_if_t<B, descr<N1 - 1>> _(char const(&text1)[N1], char const(&)[N2]) {
|
||||
return _(text1);
|
||||
constexpr enable_if_t<B, descr<N1 - 1>> const_name(char const (&text1)[N1], char const (&)[N2]) {
|
||||
return const_name(text1);
|
||||
}
|
||||
template <bool B, size_t N1, size_t N2>
|
||||
constexpr enable_if_t<!B, descr<N2 - 1>> _(char const(&)[N1], char const(&text2)[N2]) {
|
||||
return _(text2);
|
||||
constexpr enable_if_t<!B, descr<N2 - 1>> const_name(char const (&)[N1], char const (&text2)[N2]) {
|
||||
return const_name(text2);
|
||||
}
|
||||
|
||||
template <bool B, typename T1, typename T2>
|
||||
constexpr enable_if_t<B, T1> _(const T1 &d, const T2 &) { return d; }
|
||||
constexpr enable_if_t<B, T1> const_name(const T1 &d, const T2 &) {
|
||||
return d;
|
||||
}
|
||||
template <bool B, typename T1, typename T2>
|
||||
constexpr enable_if_t<!B, T2> _(const T1 &, const T2 &d) { return d; }
|
||||
constexpr enable_if_t<!B, T2> const_name(const T1 &, const T2 &d) {
|
||||
return d;
|
||||
}
|
||||
|
||||
template <size_t Size> auto constexpr _() -> decltype(int_to_str<Size / 10, Size % 10>::digits) {
|
||||
template <size_t Size>
|
||||
auto constexpr const_name() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
||||
return int_to_str<Size / 10, Size % 10>::digits;
|
||||
}
|
||||
|
||||
template <typename Type> constexpr descr<1, Type> _() { return {'%'}; }
|
||||
template <typename Type>
|
||||
constexpr descr<1, Type> const_name() {
|
||||
return {'%'};
|
||||
}
|
||||
|
||||
// If "_" is defined as a macro, py::detail::_ cannot be provided.
|
||||
// It is therefore best to use py::detail::const_name universally.
|
||||
// This block is for backward compatibility only.
|
||||
// (The const_name code is repeated to avoid introducing a "_" #define ourselves.)
|
||||
#ifndef _
|
||||
# define PYBIND11_DETAIL_UNDERSCORE_BACKWARD_COMPATIBILITY
|
||||
template <size_t N>
|
||||
constexpr descr<N - 1> _(char const (&text)[N]) {
|
||||
return const_name<N>(text);
|
||||
}
|
||||
template <bool B, size_t N1, size_t N2>
|
||||
constexpr enable_if_t<B, descr<N1 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
|
||||
return const_name<B, N1, N2>(text1, text2);
|
||||
}
|
||||
template <bool B, size_t N1, size_t N2>
|
||||
constexpr enable_if_t<!B, descr<N2 - 1>> _(char const (&text1)[N1], char const (&text2)[N2]) {
|
||||
return const_name<B, N1, N2>(text1, text2);
|
||||
}
|
||||
template <bool B, typename T1, typename T2>
|
||||
constexpr enable_if_t<B, T1> _(const T1 &d1, const T2 &d2) {
|
||||
return const_name<B, T1, T2>(d1, d2);
|
||||
}
|
||||
template <bool B, typename T1, typename T2>
|
||||
constexpr enable_if_t<!B, T2> _(const T1 &d1, const T2 &d2) {
|
||||
return const_name<B, T1, T2>(d1, d2);
|
||||
}
|
||||
|
||||
template <size_t Size>
|
||||
auto constexpr _() -> remove_cv_t<decltype(int_to_str<Size / 10, Size % 10>::digits)> {
|
||||
return const_name<Size>();
|
||||
}
|
||||
template <typename Type>
|
||||
constexpr descr<1, Type> _() {
|
||||
return const_name<Type>();
|
||||
}
|
||||
#endif // #ifndef _
|
||||
|
||||
constexpr descr<0> concat() { return {}; }
|
||||
|
||||
template <size_t N, typename... Ts>
|
||||
constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) { return descr; }
|
||||
constexpr descr<N, Ts...> concat(const descr<N, Ts...> &descr) {
|
||||
return descr;
|
||||
}
|
||||
|
||||
template <size_t N, typename... Ts, typename... Args>
|
||||
constexpr auto concat(const descr<N, Ts...> &d, const Args &...args)
|
||||
-> decltype(std::declval<descr<N + 2, Ts...>>() + concat(args...)) {
|
||||
return d + _(", ") + concat(args...);
|
||||
return d + const_name(", ") + concat(args...);
|
||||
}
|
||||
|
||||
template <size_t N, typename... Ts>
|
||||
constexpr descr<N + 2, Ts...> type_descr(const descr<N, Ts...> &descr) {
|
||||
return _("{") + descr + _("}");
|
||||
return const_name("{") + descr + const_name("}");
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
292
3rdparty/pybind11/include/pybind11/detail/init.h
vendored
292
3rdparty/pybind11/include/pybind11/detail/init.h
vendored
@ -22,9 +22,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename> using cast_op_type = value_and_holder &;
|
||||
operator value_and_holder &() { return *value; }
|
||||
static constexpr auto name = _<value_and_holder>();
|
||||
template <typename>
|
||||
using cast_op_type = value_and_holder &;
|
||||
explicit operator value_and_holder &() { return *value; }
|
||||
static constexpr auto name = const_name<value_and_holder>();
|
||||
|
||||
private:
|
||||
value_and_holder *value = nullptr;
|
||||
@ -33,15 +34,21 @@ private:
|
||||
PYBIND11_NAMESPACE_BEGIN(initimpl)
|
||||
|
||||
inline void no_nullptr(void *ptr) {
|
||||
if (!ptr) throw type_error("pybind11::init(): factory function returned nullptr");
|
||||
if (!ptr) {
|
||||
throw type_error("pybind11::init(): factory function returned nullptr");
|
||||
}
|
||||
}
|
||||
|
||||
// Implementing functions for all forms of py::init<...> and py::init(...)
|
||||
template <typename Class> using Cpp = typename Class::type;
|
||||
template <typename Class> using Alias = typename Class::type_alias;
|
||||
template <typename Class> using Holder = typename Class::holder_type;
|
||||
template <typename Class>
|
||||
using Cpp = typename Class::type;
|
||||
template <typename Class>
|
||||
using Alias = typename Class::type_alias;
|
||||
template <typename Class>
|
||||
using Holder = typename Class::holder_type;
|
||||
|
||||
template <typename Class> using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>;
|
||||
template <typename Class>
|
||||
using is_alias_constructible = std::is_constructible<Alias<Class>, Cpp<Class> &&>;
|
||||
|
||||
// Takes a Cpp pointer and returns true if it actually is a polymorphic Alias instance.
|
||||
template <typename Class, enable_if_t<Class::has_alias, int> = 0>
|
||||
@ -50,17 +57,27 @@ bool is_alias(Cpp<Class> *ptr) {
|
||||
}
|
||||
// Failing fallback version of the above for a no-alias class (always returns false)
|
||||
template <typename /*Class*/>
|
||||
constexpr bool is_alias(void *) { return false; }
|
||||
constexpr bool is_alias(void *) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Constructs and returns a new object; if the given arguments don't map to a constructor, we fall
|
||||
// back to brace aggregate initiailization so that for aggregate initialization can be used with
|
||||
// py::init, e.g. `py::init<int, int>` to initialize a `struct T { int a; int b; }`. For
|
||||
// non-aggregate types, we need to use an ordinary T(...) constructor (invoking as `T{...}` usually
|
||||
// works, but will not do the expected thing when `T` has an `initializer_list<T>` constructor).
|
||||
template <typename Class, typename... Args, detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0>
|
||||
inline Class *construct_or_initialize(Args &&...args) { return new Class(std::forward<Args>(args)...); }
|
||||
template <typename Class, typename... Args, detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0>
|
||||
inline Class *construct_or_initialize(Args &&...args) { return new Class{std::forward<Args>(args)...}; }
|
||||
template <typename Class,
|
||||
typename... Args,
|
||||
detail::enable_if_t<std::is_constructible<Class, Args...>::value, int> = 0>
|
||||
inline Class *construct_or_initialize(Args &&...args) {
|
||||
return new Class(std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename Class,
|
||||
typename... Args,
|
||||
detail::enable_if_t<!std::is_constructible<Class, Args...>::value, int> = 0>
|
||||
inline Class *construct_or_initialize(Args &&...args) {
|
||||
return new Class{std::forward<Args>(args)...};
|
||||
}
|
||||
|
||||
// Attempts to constructs an alias using a `Alias(Cpp &&)` constructor. This allows types with
|
||||
// an alias to provide only a single Cpp factory function as long as the Alias can be
|
||||
@ -69,12 +86,14 @@ inline Class *construct_or_initialize(Args &&...args) { return new Class{std::fo
|
||||
// inherit all the base class constructors.
|
||||
template <typename Class>
|
||||
void construct_alias_from_cpp(std::true_type /*is_alias_constructible*/,
|
||||
value_and_holder &v_h, Cpp<Class> &&base) {
|
||||
value_and_holder &v_h,
|
||||
Cpp<Class> &&base) {
|
||||
v_h.value_ptr() = new Alias<Class>(std::move(base));
|
||||
}
|
||||
template <typename Class>
|
||||
[[noreturn]] void construct_alias_from_cpp(std::false_type /*!is_alias_constructible*/,
|
||||
value_and_holder &, Cpp<Class> &&) {
|
||||
value_and_holder &,
|
||||
Cpp<Class> &&) {
|
||||
throw type_error("pybind11::init(): unable to convert returned instance to required "
|
||||
"alias class: no `Alias<Class>(Class &&)` constructor available");
|
||||
}
|
||||
@ -84,8 +103,8 @@ template <typename Class>
|
||||
template <typename Class>
|
||||
void construct(...) {
|
||||
static_assert(!std::is_same<Class, Class>::value /* always false */,
|
||||
"pybind11::init(): init function must return a compatible pointer, "
|
||||
"holder, or value");
|
||||
"pybind11::init(): init function must return a compatible pointer, "
|
||||
"holder, or value");
|
||||
}
|
||||
|
||||
// Pointer return v1: the factory function returns a class pointer for a registered class.
|
||||
@ -94,8 +113,9 @@ void construct(...) {
|
||||
// construct an Alias from the returned base instance.
|
||||
template <typename Class>
|
||||
void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||
no_nullptr(ptr);
|
||||
if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) {
|
||||
// We're going to try to construct an alias by moving the cpp type. Whether or not
|
||||
// that succeeds, we still need to destroy the original cpp pointer (either the
|
||||
// moved away leftover, if the alias construction works, or the value itself if we
|
||||
@ -105,7 +125,7 @@ void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
|
||||
// the holder and destruction happens when we leave the C++ scope, and the holder
|
||||
// class gets to handle the destruction however it likes.
|
||||
v_h.value_ptr() = ptr;
|
||||
v_h.set_instance_registered(true); // To prevent init_instance from registering it
|
||||
v_h.set_instance_registered(true); // To prevent init_instance from registering it
|
||||
v_h.type->init_instance(v_h.inst, nullptr); // Set up the holder
|
||||
Holder<Class> temp_holder(std::move(v_h.holder<Holder<Class>>())); // Steal the holder
|
||||
v_h.type->dealloc(v_h); // Destroys the moved-out holder remains, resets value ptr to null
|
||||
@ -128,15 +148,18 @@ void construct(value_and_holder &v_h, Alias<Class> *alias_ptr, bool) {
|
||||
|
||||
// Holder return: copy its pointer, and move or copy the returned holder into the new instance's
|
||||
// holder. This also handles types like std::shared_ptr<T> and std::unique_ptr<T> where T is a
|
||||
// derived type (through those holder's implicit conversion from derived class holder constructors).
|
||||
// derived type (through those holder's implicit conversion from derived class holder
|
||||
// constructors).
|
||||
template <typename Class>
|
||||
void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||
auto *ptr = holder_helper<Holder<Class>>::get(holder);
|
||||
no_nullptr(ptr);
|
||||
// If we need an alias, check that the held pointer is actually an alias instance
|
||||
if (Class::has_alias && need_alias && !is_alias<Class>(ptr))
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) {
|
||||
throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
|
||||
"is not an alias instance");
|
||||
}
|
||||
|
||||
v_h.value_ptr() = ptr;
|
||||
v_h.type->init_instance(v_h.inst, &holder);
|
||||
@ -148,12 +171,14 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
|
||||
// need it, we simply move-construct the cpp value into a new instance.
|
||||
template <typename Class>
|
||||
void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
|
||||
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
|
||||
static_assert(std::is_move_constructible<Cpp<Class>>::value,
|
||||
"pybind11::init() return-by-value factory function requires a movable class");
|
||||
if (Class::has_alias && need_alias)
|
||||
"pybind11::init() return-by-value factory function requires a movable class");
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias) {
|
||||
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
|
||||
else
|
||||
} else {
|
||||
v_h.value_ptr() = new Cpp<Class>(std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
// return-by-value version 2: returning a value of the alias type itself. We move-construct an
|
||||
@ -161,7 +186,8 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
|
||||
// cases where Alias initialization is always desired.
|
||||
template <typename Class>
|
||||
void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
|
||||
static_assert(std::is_move_constructible<Alias<Class>>::value,
|
||||
static_assert(
|
||||
std::is_move_constructible<Alias<Class>>::value,
|
||||
"pybind11::init() return-by-alias-value factory function requires a movable alias class");
|
||||
v_h.value_ptr() = new Alias<Class>(std::move(result));
|
||||
}
|
||||
@ -170,48 +196,76 @@ void construct(value_and_holder &v_h, Alias<Class> &&result, bool) {
|
||||
template <typename... Args>
|
||||
struct constructor {
|
||||
template <typename Class, typename... Extra, enable_if_t<!Class::has_alias, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
cl.def("__init__", [](value_and_holder &v_h, Args... args) {
|
||||
v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
}
|
||||
|
||||
template <typename Class, typename... Extra,
|
||||
enable_if_t<Class::has_alias &&
|
||||
std::is_constructible<Cpp<Class>, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
cl.def("__init__", [](value_and_holder &v_h, Args... args) {
|
||||
if (Py_TYPE(v_h.inst) == v_h.type->type)
|
||||
static void execute(Class &cl, const Extra &...extra) {
|
||||
cl.def(
|
||||
"__init__",
|
||||
[](value_and_holder &v_h, Args... args) {
|
||||
v_h.value_ptr() = construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||
else
|
||||
v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
|
||||
template <typename Class, typename... Extra,
|
||||
enable_if_t<Class::has_alias &&
|
||||
!std::is_constructible<Cpp<Class>, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
cl.def("__init__", [](value_and_holder &v_h, Args... args) {
|
||||
v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
template <typename Class,
|
||||
typename... Extra,
|
||||
enable_if_t<Class::has_alias && std::is_constructible<Cpp<Class>, Args...>::value,
|
||||
int> = 0>
|
||||
static void execute(Class &cl, const Extra &...extra) {
|
||||
cl.def(
|
||||
"__init__",
|
||||
[](value_and_holder &v_h, Args... args) {
|
||||
if (Py_TYPE(v_h.inst) == v_h.type->type) {
|
||||
v_h.value_ptr()
|
||||
= construct_or_initialize<Cpp<Class>>(std::forward<Args>(args)...);
|
||||
} else {
|
||||
v_h.value_ptr()
|
||||
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
}
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
|
||||
template <typename Class,
|
||||
typename... Extra,
|
||||
enable_if_t<Class::has_alias && !std::is_constructible<Cpp<Class>, Args...>::value,
|
||||
int> = 0>
|
||||
static void execute(Class &cl, const Extra &...extra) {
|
||||
cl.def(
|
||||
"__init__",
|
||||
[](value_and_holder &v_h, Args... args) {
|
||||
v_h.value_ptr()
|
||||
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
};
|
||||
|
||||
// Implementing class for py::init_alias<...>()
|
||||
template <typename... Args> struct alias_constructor {
|
||||
template <typename Class, typename... Extra,
|
||||
enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value, int> = 0>
|
||||
static void execute(Class &cl, const Extra&... extra) {
|
||||
cl.def("__init__", [](value_and_holder &v_h, Args... args) {
|
||||
v_h.value_ptr() = construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
template <typename... Args>
|
||||
struct alias_constructor {
|
||||
template <typename Class,
|
||||
typename... Extra,
|
||||
enable_if_t<Class::has_alias && std::is_constructible<Alias<Class>, Args...>::value,
|
||||
int> = 0>
|
||||
static void execute(Class &cl, const Extra &...extra) {
|
||||
cl.def(
|
||||
"__init__",
|
||||
[](value_and_holder &v_h, Args... args) {
|
||||
v_h.value_ptr()
|
||||
= construct_or_initialize<Alias<Class>>(std::forward<Args>(args)...);
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
};
|
||||
|
||||
// Implementation class for py::init(Func) and py::init(Func, AliasFunc)
|
||||
template <typename CFunc, typename AFunc = void_type (*)(),
|
||||
typename = function_signature_t<CFunc>, typename = function_signature_t<AFunc>>
|
||||
template <typename CFunc,
|
||||
typename AFunc = void_type (*)(),
|
||||
typename = function_signature_t<CFunc>,
|
||||
typename = function_signature_t<AFunc>>
|
||||
struct factory;
|
||||
|
||||
// Specialization for py::init(Func)
|
||||
@ -219,7 +273,8 @@ template <typename Func, typename Return, typename... Args>
|
||||
struct factory<Func, void_type (*)(), Return(Args...)> {
|
||||
remove_reference_t<Func> class_factory;
|
||||
|
||||
factory(Func &&f) : class_factory(std::forward<Func>(f)) { }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
factory(Func &&f) : class_factory(std::forward<Func>(f)) {}
|
||||
|
||||
// The given class either has no alias or has no separate alias factory;
|
||||
// this always constructs the class itself. If the class is registered with an alias
|
||||
@ -228,22 +283,32 @@ struct factory<Func, void_type (*)(), Return(Args...)> {
|
||||
// instance, or the alias needs to be constructible from a `Class &&` argument.
|
||||
template <typename Class, typename... Extra>
|
||||
void execute(Class &cl, const Extra &...extra) && {
|
||||
#if defined(PYBIND11_CPP14)
|
||||
cl.def("__init__", [func = std::move(class_factory)]
|
||||
#else
|
||||
#if defined(PYBIND11_CPP14)
|
||||
cl.def(
|
||||
"__init__",
|
||||
[func = std::move(class_factory)]
|
||||
#else
|
||||
auto &func = class_factory;
|
||||
cl.def("__init__", [func]
|
||||
#endif
|
||||
(value_and_holder &v_h, Args... args) {
|
||||
construct<Class>(v_h, func(std::forward<Args>(args)...),
|
||||
Py_TYPE(v_h.inst) != v_h.type->type);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
cl.def(
|
||||
"__init__",
|
||||
[func]
|
||||
#endif
|
||||
(value_and_holder &v_h, Args... args) {
|
||||
construct<Class>(
|
||||
v_h, func(std::forward<Args>(args)...), Py_TYPE(v_h.inst) != v_h.type->type);
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
};
|
||||
|
||||
// Specialization for py::init(Func, AliasFunc)
|
||||
template <typename CFunc, typename AFunc,
|
||||
typename CReturn, typename... CArgs, typename AReturn, typename... AArgs>
|
||||
template <typename CFunc,
|
||||
typename AFunc,
|
||||
typename CReturn,
|
||||
typename... CArgs,
|
||||
typename AReturn,
|
||||
typename... AArgs>
|
||||
struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> {
|
||||
static_assert(sizeof...(CArgs) == sizeof...(AArgs),
|
||||
"pybind11::init(class_factory, alias_factory): class and alias factories "
|
||||
@ -256,29 +321,37 @@ struct factory<CFunc, AFunc, CReturn(CArgs...), AReturn(AArgs...)> {
|
||||
remove_reference_t<AFunc> alias_factory;
|
||||
|
||||
factory(CFunc &&c, AFunc &&a)
|
||||
: class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) { }
|
||||
: class_factory(std::forward<CFunc>(c)), alias_factory(std::forward<AFunc>(a)) {}
|
||||
|
||||
// The class factory is called when the `self` type passed to `__init__` is the direct
|
||||
// class (i.e. not inherited), the alias factory when `self` is a Python-side subtype.
|
||||
template <typename Class, typename... Extra>
|
||||
void execute(Class &cl, const Extra&... extra) && {
|
||||
static_assert(Class::has_alias, "The two-argument version of `py::init()` can "
|
||||
"only be used if the class has an alias");
|
||||
#if defined(PYBIND11_CPP14)
|
||||
cl.def("__init__", [class_func = std::move(class_factory), alias_func = std::move(alias_factory)]
|
||||
#else
|
||||
void execute(Class &cl, const Extra &...extra) && {
|
||||
static_assert(Class::has_alias,
|
||||
"The two-argument version of `py::init()` can "
|
||||
"only be used if the class has an alias");
|
||||
#if defined(PYBIND11_CPP14)
|
||||
cl.def(
|
||||
"__init__",
|
||||
[class_func = std::move(class_factory), alias_func = std::move(alias_factory)]
|
||||
#else
|
||||
auto &class_func = class_factory;
|
||||
auto &alias_func = alias_factory;
|
||||
cl.def("__init__", [class_func, alias_func]
|
||||
#endif
|
||||
(value_and_holder &v_h, CArgs... args) {
|
||||
if (Py_TYPE(v_h.inst) == v_h.type->type)
|
||||
// If the instance type equals the registered type we don't have inheritance, so
|
||||
// don't need the alias and can construct using the class function:
|
||||
construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false);
|
||||
else
|
||||
construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
cl.def(
|
||||
"__init__",
|
||||
[class_func, alias_func]
|
||||
#endif
|
||||
(value_and_holder &v_h, CArgs... args) {
|
||||
if (Py_TYPE(v_h.inst) == v_h.type->type) {
|
||||
// If the instance type equals the registered type we don't have inheritance,
|
||||
// so don't need the alias and can construct using the class function:
|
||||
construct<Class>(v_h, class_func(std::forward<CArgs>(args)...), false);
|
||||
} else {
|
||||
construct<Class>(v_h, alias_func(std::forward<CArgs>(args)...), true);
|
||||
}
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
};
|
||||
|
||||
@ -289,20 +362,34 @@ void setstate(value_and_holder &v_h, T &&result, bool need_alias) {
|
||||
}
|
||||
|
||||
/// Set both the C++ and Python states
|
||||
template <typename Class, typename T, typename O,
|
||||
template <typename Class,
|
||||
typename T,
|
||||
typename O,
|
||||
enable_if_t<std::is_convertible<O, handle>::value, int> = 0>
|
||||
void setstate(value_and_holder &v_h, std::pair<T, O> &&result, bool need_alias) {
|
||||
construct<Class>(v_h, std::move(result.first), need_alias);
|
||||
setattr((PyObject *) v_h.inst, "__dict__", result.second);
|
||||
auto d = handle(result.second);
|
||||
if (PyDict_Check(d.ptr()) && PyDict_Size(d.ptr()) == 0) {
|
||||
// Skipping setattr below, to not force use of py::dynamic_attr() for Class unnecessarily.
|
||||
// See PR #2972 for details.
|
||||
return;
|
||||
}
|
||||
setattr((PyObject *) v_h.inst, "__dict__", d);
|
||||
}
|
||||
|
||||
/// Implementation for py::pickle(GetState, SetState)
|
||||
template <typename Get, typename Set,
|
||||
typename = function_signature_t<Get>, typename = function_signature_t<Set>>
|
||||
template <typename Get,
|
||||
typename Set,
|
||||
typename = function_signature_t<Get>,
|
||||
typename = function_signature_t<Set>>
|
||||
struct pickle_factory;
|
||||
|
||||
template <typename Get, typename Set,
|
||||
typename RetState, typename Self, typename NewInstance, typename ArgState>
|
||||
template <typename Get,
|
||||
typename Set,
|
||||
typename RetState,
|
||||
typename Self,
|
||||
typename NewInstance,
|
||||
typename ArgState>
|
||||
struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> {
|
||||
static_assert(std::is_same<intrinsic_t<RetState>, intrinsic_t<ArgState>>::value,
|
||||
"The type returned by `__getstate__` must be the same "
|
||||
@ -311,26 +398,31 @@ struct pickle_factory<Get, Set, RetState(Self), NewInstance(ArgState)> {
|
||||
remove_reference_t<Get> get;
|
||||
remove_reference_t<Set> set;
|
||||
|
||||
pickle_factory(Get get, Set set)
|
||||
: get(std::forward<Get>(get)), set(std::forward<Set>(set)) { }
|
||||
pickle_factory(Get get, Set set) : get(std::forward<Get>(get)), set(std::forward<Set>(set)) {}
|
||||
|
||||
template <typename Class, typename... Extra>
|
||||
void execute(Class &cl, const Extra &...extra) && {
|
||||
cl.def("__getstate__", std::move(get));
|
||||
|
||||
#if defined(PYBIND11_CPP14)
|
||||
cl.def("__setstate__", [func = std::move(set)]
|
||||
cl.def(
|
||||
"__setstate__",
|
||||
[func = std::move(set)]
|
||||
#else
|
||||
auto &func = set;
|
||||
cl.def("__setstate__", [func]
|
||||
cl.def(
|
||||
"__setstate__",
|
||||
[func]
|
||||
#endif
|
||||
(value_and_holder &v_h, ArgState state) {
|
||||
setstate<Class>(v_h, func(std::forward<ArgState>(state)),
|
||||
Py_TYPE(v_h.inst) != v_h.type->type);
|
||||
}, is_new_style_constructor(), extra...);
|
||||
(value_and_holder &v_h, ArgState state) {
|
||||
setstate<Class>(
|
||||
v_h, func(std::forward<ArgState>(state)), Py_TYPE(v_h.inst) != v_h.type->type);
|
||||
},
|
||||
is_new_style_constructor(),
|
||||
extra...);
|
||||
}
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(initimpl)
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(pybind11)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
@ -11,8 +11,32 @@
|
||||
|
||||
#include "../pytypes.h"
|
||||
|
||||
#include <exception>
|
||||
|
||||
/// Tracks the `internals` and `type_info` ABI version independent of the main library version.
|
||||
///
|
||||
/// Some portions of the code use an ABI that is conditional depending on this
|
||||
/// version number. That allows ABI-breaking changes to be "pre-implemented".
|
||||
/// Once the default version number is incremented, the conditional logic that
|
||||
/// no longer applies can be removed. Additionally, users that need not
|
||||
/// maintain ABI compatibility can increase the version number in order to take
|
||||
/// advantage of any functionality/efficiency improvements that depend on the
|
||||
/// newer ABI.
|
||||
///
|
||||
/// WARNING: If you choose to manually increase the ABI version, note that
|
||||
/// pybind11 may not be tested as thoroughly with a non-default ABI version, and
|
||||
/// further ABI-incompatible changes may be made before the ABI is officially
|
||||
/// changed to the new version.
|
||||
#ifndef PYBIND11_INTERNALS_VERSION
|
||||
# define PYBIND11_INTERNALS_VERSION 4
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
using ExceptionTranslator = void (*)(std::exception_ptr);
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
// Forward declarations
|
||||
inline PyTypeObject *make_static_property_type();
|
||||
inline PyTypeObject *make_default_metaclass();
|
||||
@ -21,30 +45,59 @@ 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
|
||||
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr
|
||||
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
|
||||
# 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)
|
||||
#else
|
||||
// Usually an int but a long on Cygwin64 with Python 3.x
|
||||
# define PYBIND11_TLS_KEY_INIT(var) decltype(PyThread_create_key()) var = 0
|
||||
# define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
|
||||
# if PY_MAJOR_VERSION < 3
|
||||
# define PYBIND11_TLS_DELETE_VALUE(key) \
|
||||
PyThread_delete_key_value(key)
|
||||
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \
|
||||
do { \
|
||||
PyThread_delete_key_value((key)); \
|
||||
PyThread_set_key_value((key), (value)); \
|
||||
} while (false)
|
||||
// Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
|
||||
// `Py_LIMITED_API` anyway.
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
# define PYBIND11_TLS_KEY_REF Py_tss_t &
|
||||
# ifdef __GNUC__
|
||||
// Clang on macOS warns due to `Py_tss_NEEDS_INIT` not specifying an initializer
|
||||
// for every field.
|
||||
# define PYBIND11_TLS_KEY_INIT(var) \
|
||||
_Pragma("GCC diagnostic push") /**/ \
|
||||
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
|
||||
Py_tss_t var \
|
||||
= Py_tss_NEEDS_INIT; \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
# else
|
||||
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT;
|
||||
# endif
|
||||
# define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0)
|
||||
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key))
|
||||
# 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
|
||||
# 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))
|
||||
# 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) \
|
||||
(((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0))
|
||||
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
|
||||
# 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
|
||||
# define PYBIND11_TLS_FREE(key) (void)key
|
||||
#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
|
||||
@ -66,8 +119,9 @@ struct type_hash {
|
||||
size_t operator()(const std::type_index &t) const {
|
||||
size_t hash = 5381;
|
||||
const char *ptr = t.name();
|
||||
while (auto c = static_cast<unsigned char>(*ptr++))
|
||||
while (auto c = static_cast<unsigned char>(*ptr++)) {
|
||||
hash = (hash * 33) ^ c;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
@ -83,9 +137,9 @@ template <typename value_type>
|
||||
using type_map = std::unordered_map<std::type_index, value_type, type_hash, type_equal_to>;
|
||||
|
||||
struct override_hash {
|
||||
inline size_t operator()(const std::pair<const PyObject *, const char *>& v) const {
|
||||
inline size_t operator()(const std::pair<const PyObject *, const char *> &v) const {
|
||||
size_t value = std::hash<const void *>()(v.first);
|
||||
value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value<<6) + (value>>2);
|
||||
value ^= std::hash<const void *>()(v.second) + 0x9e3779b9 + (value << 6) + (value >> 2);
|
||||
return value;
|
||||
}
|
||||
};
|
||||
@ -94,30 +148,44 @@ struct override_hash {
|
||||
/// Whenever binary incompatible changes are made to this structure,
|
||||
/// `PYBIND11_INTERNALS_VERSION` must be incremented.
|
||||
struct internals {
|
||||
type_map<type_info *> registered_types_cpp; // std::type_index -> pybind11's type information
|
||||
std::unordered_map<PyTypeObject *, std::vector<type_info *>> registered_types_py; // PyTypeObject* -> base type_info(s)
|
||||
std::unordered_multimap<const void *, instance*> registered_instances; // void * -> instance*
|
||||
std::unordered_set<std::pair<const PyObject *, const char *>, override_hash> inactive_override_cache;
|
||||
// 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*
|
||||
std::unordered_set<std::pair<const PyObject *, const char *>, override_hash>
|
||||
inactive_override_cache;
|
||||
type_map<std::vector<bool (*)(PyObject *, void *&)>> direct_conversions;
|
||||
std::unordered_map<const PyObject *, std::vector<PyObject *>> patients;
|
||||
std::forward_list<void (*) (std::exception_ptr)> registered_exception_translators;
|
||||
std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across extensions
|
||||
std::vector<PyObject *> loader_patient_stack; // Used by `loader_life_support`
|
||||
std::forward_list<std::string> static_strings; // Stores the std::strings backing detail::c_str()
|
||||
std::forward_list<ExceptionTranslator> registered_exception_translators;
|
||||
std::unordered_map<std::string, void *> shared_data; // Custom data to be shared across
|
||||
// extensions
|
||||
#if PYBIND11_INTERNALS_VERSION == 4
|
||||
std::vector<PyObject *> unused_loader_patient_stack_remove_at_v5;
|
||||
#endif
|
||||
std::forward_list<std::string> static_strings; // Stores the std::strings backing
|
||||
// detail::c_str()
|
||||
PyTypeObject *static_property_type;
|
||||
PyTypeObject *default_metaclass;
|
||||
PyObject *instance_base;
|
||||
#if defined(WITH_THREAD)
|
||||
PYBIND11_TLS_KEY_INIT(tstate);
|
||||
PYBIND11_TLS_KEY_INIT(tstate)
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||
# endif // PYBIND11_INTERNALS_VERSION > 4
|
||||
PyInterpreterState *istate = nullptr;
|
||||
~internals() {
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
PYBIND11_TLS_FREE(loader_life_support_tls_key);
|
||||
# endif // PYBIND11_INTERNALS_VERSION > 4
|
||||
|
||||
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
|
||||
// That *SHOULD BE* fine. The following details what happens whe PyThread_tss_free is called.
|
||||
// PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does nothing.
|
||||
// PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
|
||||
// PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX). Neither
|
||||
// of those have anything to do with CPython internals.
|
||||
// PyMem_RawFree *requires* that the `tstate` be allocated with the CPython allocator.
|
||||
// That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
|
||||
// called. PYBIND11_TLS_FREE is PyThread_tss_free on python 3.7+. On older python, it does
|
||||
// nothing. PyThread_tss_free calls PyThread_tss_delete and PyMem_RawFree.
|
||||
// PyThread_tss_delete just calls TlsFree (on Windows) or pthread_key_delete (on *NIX).
|
||||
// Neither of those have anything to do with CPython internals. PyMem_RawFree *requires*
|
||||
// that the `tstate` be allocated with the CPython allocator.
|
||||
PYBIND11_TLS_FREE(tstate);
|
||||
}
|
||||
#endif
|
||||
@ -132,14 +200,16 @@ struct type_info {
|
||||
void *(*operator_new)(size_t);
|
||||
void (*init_instance)(instance *, const void *);
|
||||
void (*dealloc)(value_and_holder &v_h);
|
||||
std::vector<PyObject *(*)(PyObject *, PyTypeObject *)> implicit_conversions;
|
||||
std::vector<std::pair<const std::type_info *, void *(*)(void *)>> implicit_casts;
|
||||
std::vector<PyObject *(*) (PyObject *, PyTypeObject *)> implicit_conversions;
|
||||
std::vector<std::pair<const std::type_info *, void *(*) (void *)>> implicit_casts;
|
||||
std::vector<bool (*)(PyObject *, void *&)> *direct_conversions;
|
||||
buffer_info *(*get_buffer)(PyObject *, void *) = nullptr;
|
||||
void *get_buffer_data = nullptr;
|
||||
void *(*module_local_load)(PyObject *, const type_info *) = nullptr;
|
||||
/* A simple type never occurs as a (direct or indirect) parent
|
||||
* of a class that makes use of multiple inheritance */
|
||||
* of a class that makes use of multiple inheritance.
|
||||
* A type can be simple even if it has non-simple ancestors as long as it has no descendants.
|
||||
*/
|
||||
bool simple_type : 1;
|
||||
/* True if there is no multiple inheritance in this type's inheritance tree */
|
||||
bool simple_ancestors : 1;
|
||||
@ -149,72 +219,73 @@ struct type_info {
|
||||
bool module_local : 1;
|
||||
};
|
||||
|
||||
/// Tracks the `internals` and `type_info` ABI version independent of the main library version
|
||||
#define PYBIND11_INTERNALS_VERSION 4
|
||||
|
||||
/// On MSVC, debug and release builds are not ABI-compatible!
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
# define PYBIND11_BUILD_TYPE "_debug"
|
||||
# define PYBIND11_BUILD_TYPE "_debug"
|
||||
#else
|
||||
# define PYBIND11_BUILD_TYPE ""
|
||||
# define PYBIND11_BUILD_TYPE ""
|
||||
#endif
|
||||
|
||||
/// Let's assume that different compilers are ABI-incompatible.
|
||||
/// A user can manually set this string if they know their
|
||||
/// compiler is compatible.
|
||||
#ifndef PYBIND11_COMPILER_TYPE
|
||||
# if defined(_MSC_VER)
|
||||
# define PYBIND11_COMPILER_TYPE "_msvc"
|
||||
# elif defined(__INTEL_COMPILER)
|
||||
# define PYBIND11_COMPILER_TYPE "_icc"
|
||||
# elif defined(__clang__)
|
||||
# define PYBIND11_COMPILER_TYPE "_clang"
|
||||
# elif defined(__PGI)
|
||||
# define PYBIND11_COMPILER_TYPE "_pgi"
|
||||
# elif defined(__MINGW32__)
|
||||
# define PYBIND11_COMPILER_TYPE "_mingw"
|
||||
# elif defined(__CYGWIN__)
|
||||
# define PYBIND11_COMPILER_TYPE "_gcc_cygwin"
|
||||
# elif defined(__GNUC__)
|
||||
# define PYBIND11_COMPILER_TYPE "_gcc"
|
||||
# else
|
||||
# define PYBIND11_COMPILER_TYPE "_unknown"
|
||||
# endif
|
||||
# if defined(_MSC_VER)
|
||||
# define PYBIND11_COMPILER_TYPE "_msvc"
|
||||
# elif defined(__INTEL_COMPILER)
|
||||
# define PYBIND11_COMPILER_TYPE "_icc"
|
||||
# elif defined(__clang__)
|
||||
# define PYBIND11_COMPILER_TYPE "_clang"
|
||||
# elif defined(__PGI)
|
||||
# define PYBIND11_COMPILER_TYPE "_pgi"
|
||||
# elif defined(__MINGW32__)
|
||||
# define PYBIND11_COMPILER_TYPE "_mingw"
|
||||
# elif defined(__CYGWIN__)
|
||||
# define PYBIND11_COMPILER_TYPE "_gcc_cygwin"
|
||||
# elif defined(__GNUC__)
|
||||
# define PYBIND11_COMPILER_TYPE "_gcc"
|
||||
# else
|
||||
# define PYBIND11_COMPILER_TYPE "_unknown"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/// Also standard libs
|
||||
#ifndef PYBIND11_STDLIB
|
||||
# if defined(_LIBCPP_VERSION)
|
||||
# define PYBIND11_STDLIB "_libcpp"
|
||||
# elif defined(__GLIBCXX__) || defined(__GLIBCPP__)
|
||||
# define PYBIND11_STDLIB "_libstdcpp"
|
||||
# else
|
||||
# define PYBIND11_STDLIB ""
|
||||
# endif
|
||||
# if defined(_LIBCPP_VERSION)
|
||||
# define PYBIND11_STDLIB "_libcpp"
|
||||
# elif defined(__GLIBCXX__) || defined(__GLIBCPP__)
|
||||
# define PYBIND11_STDLIB "_libstdcpp"
|
||||
# else
|
||||
# define PYBIND11_STDLIB ""
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/// On Linux/OSX, changes in __GXX_ABI_VERSION__ indicate ABI incompatibility.
|
||||
#ifndef PYBIND11_BUILD_ABI
|
||||
# if defined(__GXX_ABI_VERSION)
|
||||
# define PYBIND11_BUILD_ABI "_cxxabi" PYBIND11_TOSTRING(__GXX_ABI_VERSION)
|
||||
# else
|
||||
# define PYBIND11_BUILD_ABI ""
|
||||
# endif
|
||||
# if defined(__GXX_ABI_VERSION)
|
||||
# define PYBIND11_BUILD_ABI "_cxxabi" PYBIND11_TOSTRING(__GXX_ABI_VERSION)
|
||||
# else
|
||||
# define PYBIND11_BUILD_ABI ""
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef PYBIND11_INTERNALS_KIND
|
||||
# if defined(WITH_THREAD)
|
||||
# define PYBIND11_INTERNALS_KIND ""
|
||||
# else
|
||||
# define PYBIND11_INTERNALS_KIND "_without_thread"
|
||||
# endif
|
||||
# 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 "__"
|
||||
#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 "__"
|
||||
|
||||
#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 "__"
|
||||
#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 "__"
|
||||
|
||||
/// Each module locally stores a pointer to the `internals` data. The data
|
||||
/// itself is shared among modules with the same `PYBIND11_INTERNALS_ID`.
|
||||
@ -223,21 +294,93 @@ inline internals **&get_internals_pp() {
|
||||
return internals_pp;
|
||||
}
|
||||
|
||||
// forward decl
|
||||
inline void translate_exception(std::exception_ptr);
|
||||
|
||||
template <class T,
|
||||
enable_if_t<std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
|
||||
bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
|
||||
std::exception_ptr nested = exc.nested_ptr();
|
||||
if (nested != nullptr && nested != p) {
|
||||
translate_exception(nested);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T,
|
||||
enable_if_t<!std::is_same<std::nested_exception, remove_cvref_t<T>>::value, int> = 0>
|
||||
bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
|
||||
if (const auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(exc))) {
|
||||
return handle_nested_exception(*nep, p);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool raise_err(PyObject *exc_type, const char *msg) {
|
||||
if (PyErr_Occurred()) {
|
||||
raise_from(exc_type, msg);
|
||||
return true;
|
||||
}
|
||||
PyErr_SetString(exc_type, msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void translate_exception(std::exception_ptr p) {
|
||||
if (!p) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
} catch (error_already_set &e) { e.restore(); return;
|
||||
} catch (const builtin_exception &e) { e.set_error(); return;
|
||||
} catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return;
|
||||
} catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
||||
} catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
||||
} catch (const std::length_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
||||
} catch (const std::out_of_range &e) { PyErr_SetString(PyExc_IndexError, e.what()); return;
|
||||
} catch (const std::range_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
|
||||
} catch (const std::overflow_error &e) { PyErr_SetString(PyExc_OverflowError, e.what()); return;
|
||||
} catch (const std::exception &e) { PyErr_SetString(PyExc_RuntimeError, e.what()); return;
|
||||
std::rethrow_exception(p);
|
||||
} catch (error_already_set &e) {
|
||||
handle_nested_exception(e, p);
|
||||
e.restore();
|
||||
return;
|
||||
} catch (const builtin_exception &e) {
|
||||
// Could not use template since it's an abstract class.
|
||||
if (const auto *nep = dynamic_cast<const std::nested_exception *>(std::addressof(e))) {
|
||||
handle_nested_exception(*nep, p);
|
||||
}
|
||||
e.set_error();
|
||||
return;
|
||||
} catch (const std::bad_alloc &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_MemoryError, e.what());
|
||||
return;
|
||||
} catch (const std::domain_error &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_ValueError, e.what());
|
||||
return;
|
||||
} catch (const std::invalid_argument &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_ValueError, e.what());
|
||||
return;
|
||||
} catch (const std::length_error &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_ValueError, e.what());
|
||||
return;
|
||||
} catch (const std::out_of_range &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_IndexError, e.what());
|
||||
return;
|
||||
} catch (const std::range_error &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_ValueError, e.what());
|
||||
return;
|
||||
} catch (const std::overflow_error &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_OverflowError, e.what());
|
||||
return;
|
||||
} catch (const std::exception &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_RuntimeError, e.what());
|
||||
return;
|
||||
} catch (const std::nested_exception &e) {
|
||||
handle_nested_exception(e, p);
|
||||
raise_err(PyExc_RuntimeError, "Caught an unknown nested exception!");
|
||||
return;
|
||||
} catch (...) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "Caught an unknown exception!");
|
||||
raise_err(PyExc_RuntimeError, "Caught an unknown exception!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -245,28 +388,36 @@ inline void translate_exception(std::exception_ptr p) {
|
||||
#if !defined(__GLIBCXX__)
|
||||
inline void translate_local_exception(std::exception_ptr p) {
|
||||
try {
|
||||
if (p) std::rethrow_exception(p);
|
||||
} catch (error_already_set &e) { e.restore(); return;
|
||||
} catch (const builtin_exception &e) { e.set_error(); return;
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (error_already_set &e) {
|
||||
e.restore();
|
||||
return;
|
||||
} catch (const builtin_exception &e) {
|
||||
e.set_error();
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Return a reference to the current `internals` data
|
||||
PYBIND11_NOINLINE inline internals &get_internals() {
|
||||
PYBIND11_NOINLINE internals &get_internals() {
|
||||
auto **&internals_pp = get_internals_pp();
|
||||
if (internals_pp && *internals_pp)
|
||||
if (internals_pp && *internals_pp) {
|
||||
return **internals_pp;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
gil_scoped_acquire_local() : state (PyGILState_Ensure()) {}
|
||||
gil_scoped_acquire_local() : state(PyGILState_Ensure()) {}
|
||||
~gil_scoped_acquire_local() { PyGILState_Release(state); }
|
||||
const PyGILState_STATE state;
|
||||
} gil;
|
||||
error_scope err_scope;
|
||||
|
||||
constexpr auto *id = PYBIND11_INTERNALS_ID;
|
||||
PYBIND11_STR_TYPE id(PYBIND11_INTERNALS_ID);
|
||||
auto builtins = handle(PyEval_GetBuiltins());
|
||||
if (builtins.contains(id) && isinstance<capsule>(builtins[id])) {
|
||||
internals_pp = static_cast<internals **>(capsule(builtins[id]));
|
||||
@ -276,30 +427,34 @@ PYBIND11_NOINLINE inline internals &get_internals() {
|
||||
// initial exception translator, below, so add another for our local exception classes.
|
||||
//
|
||||
// libstdc++ doesn't require this (types there are identified only by name)
|
||||
// libc++ with CPython doesn't require this (types are explicitly exported)
|
||||
// libc++ with PyPy still need it, awaiting further investigation
|
||||
#if !defined(__GLIBCXX__)
|
||||
(*internals_pp)->registered_exception_translators.push_front(&translate_local_exception);
|
||||
#endif
|
||||
} else {
|
||||
if (!internals_pp) internals_pp = new internals*();
|
||||
if (!internals_pp) {
|
||||
internals_pp = new internals *();
|
||||
}
|
||||
auto *&internals_ptr = *internals_pp;
|
||||
internals_ptr = new internals();
|
||||
#if defined(WITH_THREAD)
|
||||
|
||||
#if PY_VERSION_HEX < 0x03090000
|
||||
PyEval_InitThreads();
|
||||
#endif
|
||||
# if PY_VERSION_HEX < 0x03090000
|
||||
PyEval_InitThreads();
|
||||
# endif
|
||||
PyThreadState *tstate = PyThreadState_Get();
|
||||
#if PY_VERSION_HEX >= 0x03070000
|
||||
internals_ptr->tstate = PyThread_tss_alloc();
|
||||
if (!internals_ptr->tstate || PyThread_tss_create(internals_ptr->tstate))
|
||||
pybind11_fail("get_internals: could not successfully initialize the TSS key!");
|
||||
PyThread_tss_set(internals_ptr->tstate, tstate);
|
||||
#else
|
||||
internals_ptr->tstate = PyThread_create_key();
|
||||
if (internals_ptr->tstate == -1)
|
||||
pybind11_fail("get_internals: could not successfully initialize the TLS key!");
|
||||
PyThread_set_key_value(internals_ptr->tstate, tstate);
|
||||
#endif
|
||||
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->tstate)) {
|
||||
pybind11_fail("get_internals: could not successfully initialize the tstate TSS key!");
|
||||
}
|
||||
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate);
|
||||
|
||||
# if PYBIND11_INTERNALS_VERSION > 4
|
||||
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
|
||||
builtins[id] = capsule(internals_pp);
|
||||
@ -311,9 +466,53 @@ PYBIND11_NOINLINE inline internals &get_internals() {
|
||||
return **internals_pp;
|
||||
}
|
||||
|
||||
/// Works like `internals.registered_types_cpp`, but for module-local registered types:
|
||||
inline type_map<type_info *> ®istered_local_types_cpp() {
|
||||
static type_map<type_info *> locals{};
|
||||
// the internals struct (above) is shared between all the modules. local_internals are only
|
||||
// for a single module. Any changes made to internals may require an update to
|
||||
// PYBIND11_INTERNALS_VERSION, breaking backwards compatibility. local_internals is, by design,
|
||||
// restricted to a single module. Whether a module has local internals or not should not
|
||||
// impact any other modules, because the only things accessing the local internals is the
|
||||
// module that contains them.
|
||||
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
|
||||
|
||||
// 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
|
||||
// cache a copy in `local_internals`. If we allocated a separate TLS key for
|
||||
// each instance of `local_internals`, we could end up allocating hundreds of
|
||||
// TLS keys if hundreds of different pybind11 modules are loaded (which is a
|
||||
// plausible number).
|
||||
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||
|
||||
// Holds the shared TLS key for the loader_life_support stack.
|
||||
struct shared_loader_life_support_data {
|
||||
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
|
||||
shared_loader_life_support_data() {
|
||||
if (!PYBIND11_TLS_KEY_CREATE(loader_life_support_tls_key)) {
|
||||
pybind11_fail("local_internals: could not successfully initialize the "
|
||||
"loader_life_support TLS key!");
|
||||
}
|
||||
}
|
||||
// We can't help but leak the TLS key, because Python never unloads extension modules.
|
||||
};
|
||||
|
||||
local_internals() {
|
||||
auto &internals = get_internals();
|
||||
// Get or create the `loader_life_support_stack_key`.
|
||||
auto &ptr = internals.shared_data["_life_support"];
|
||||
if (!ptr) {
|
||||
ptr = new shared_loader_life_support_data;
|
||||
}
|
||||
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
|
||||
};
|
||||
|
||||
/// Works like `get_internals`, but for things which are locally registered.
|
||||
inline local_internals &get_local_internals() {
|
||||
static local_internals locals;
|
||||
return locals;
|
||||
}
|
||||
|
||||
@ -333,14 +532,14 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
/// Returns a named pointer that is shared among all extension modules (using the same
|
||||
/// pybind11 version) running in the current interpreter. Names starting with underscores
|
||||
/// are reserved for internal usage. Returns `nullptr` if no matching entry was found.
|
||||
inline PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
|
||||
PYBIND11_NOINLINE void *get_shared_data(const std::string &name) {
|
||||
auto &internals = detail::get_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()`.
|
||||
inline PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
|
||||
PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *data) {
|
||||
detail::get_internals().shared_data[name] = data;
|
||||
return data;
|
||||
}
|
||||
@ -348,7 +547,7 @@ inline PYBIND11_NOINLINE void *set_shared_data(const std::string &name, void *da
|
||||
/// Returns a typed reference to a shared data entry (by using `get_shared_data()`) if
|
||||
/// such entry exists. Otherwise, a new object of default-constructible type `T` is
|
||||
/// added to the shared data under the given name and a reference to it is returned.
|
||||
template<typename T>
|
||||
template <typename T>
|
||||
T &get_or_create_shared_data(const std::string &name) {
|
||||
auto &internals = detail::get_internals();
|
||||
auto it = internals.shared_data.find(name);
|
||||
|
1010
3rdparty/pybind11/include/pybind11/detail/type_caster_base.h
vendored
Normal file
1010
3rdparty/pybind11/include/pybind11/detail/type_caster_base.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@ -13,29 +13,33 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#if defined(__GNUG__)
|
||||
#include <cxxabi.h>
|
||||
# include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
/// Erase all occurrences of a substring
|
||||
inline void erase_all(std::string &string, const std::string &search) {
|
||||
for (size_t pos = 0;;) {
|
||||
pos = string.find(search, pos);
|
||||
if (pos == std::string::npos) break;
|
||||
if (pos == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
string.erase(pos, search.length());
|
||||
}
|
||||
}
|
||||
|
||||
PYBIND11_NOINLINE inline void clean_type_id(std::string &name) {
|
||||
PYBIND11_NOINLINE void clean_type_id(std::string &name) {
|
||||
#if defined(__GNUG__)
|
||||
int status = 0;
|
||||
std::unique_ptr<char, void (*)(void *)> res {
|
||||
abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free };
|
||||
if (status == 0)
|
||||
std::unique_ptr<char, void (*)(void *)> res{
|
||||
abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free};
|
||||
if (status == 0) {
|
||||
name = res.get();
|
||||
}
|
||||
#else
|
||||
detail::erase_all(name, "class ");
|
||||
detail::erase_all(name, "struct ");
|
||||
@ -43,13 +47,19 @@ PYBIND11_NOINLINE inline void clean_type_id(std::string &name) {
|
||||
#endif
|
||||
detail::erase_all(name, "pybind11::");
|
||||
}
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
/// Return a string representation of a C++ type
|
||||
template <typename T> static std::string type_id() {
|
||||
std::string name(typeid(T).name());
|
||||
inline std::string clean_type_id(const char *typeid_name) {
|
||||
std::string name(typeid_name);
|
||||
detail::clean_type_id(name);
|
||||
return name;
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
/// Return a string representation of a C++ type
|
||||
template <typename T>
|
||||
static std::string type_id() {
|
||||
return detail::clean_type_id(typeid(T).name());
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
544
3rdparty/pybind11/include/pybind11/eigen.h
vendored
544
3rdparty/pybind11/include/pybind11/eigen.h
vendored
@ -9,218 +9,266 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
/* HINT: To suppress warnings originating from the Eigen headers, use -isystem.
|
||||
See also:
|
||||
https://stackoverflow.com/questions/2579576/i-dir-vs-isystem-dir
|
||||
https://stackoverflow.com/questions/1741816/isystem-for-ms-visual-studio-c-compiler
|
||||
*/
|
||||
|
||||
#include "numpy.h"
|
||||
|
||||
#if defined(__INTEL_COMPILER)
|
||||
# pragma warning(disable: 1682) // implicit conversion of a 64-bit integral type to a smaller integral type (potential portability problem)
|
||||
#elif defined(__GNUG__) || defined(__clang__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wconversion"
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
# ifdef __clang__
|
||||
// Eigen generates a bunch of implicit-copy-constructor-is-deprecated warnings with -Wdeprecated
|
||||
// under Clang, so disable that warning here:
|
||||
# pragma GCC diagnostic ignored "-Wdeprecated"
|
||||
# endif
|
||||
# if __GNUC__ >= 7
|
||||
# pragma GCC diagnostic ignored "-Wint-in-bool-context"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// The C4127 suppression was introduced for Eigen 3.4.0. In theory we could
|
||||
// make it version specific, or even remove it later, but considering that
|
||||
// 1. C4127 is generally far more distracting than useful for modern template code, and
|
||||
// 2. we definitely want to ignore any MSVC warnings originating from Eigen code,
|
||||
// it is probably best to keep this around indefinitely.
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
||||
# pragma warning(disable: 4996) // warning C4996: std::unary_negate is deprecated in C++17
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable : 4127) // C4127: conditional expression is constant
|
||||
# pragma warning(disable : 5054) // https://github.com/pybind/pybind11/pull/3741
|
||||
// C5054: operator '&': deprecated between enumerations of different types
|
||||
#elif defined(__MINGW32__)
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/SparseCore>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#elif defined(__MINGW32__)
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
// Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit
|
||||
// move constructors that break things. We could detect this an explicitly copy, but an extra copy
|
||||
// of matrices seems highly undesirable.
|
||||
static_assert(EIGEN_VERSION_AT_LEAST(3,2,7), "Eigen support in pybind11 requires Eigen >= 3.2.7");
|
||||
static_assert(EIGEN_VERSION_AT_LEAST(3, 2, 7),
|
||||
"Eigen support in pybind11 requires Eigen >= 3.2.7");
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
// Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides:
|
||||
using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
|
||||
template <typename MatrixType> using EigenDRef = Eigen::Ref<MatrixType, 0, EigenDStride>;
|
||||
template <typename MatrixType> using EigenDMap = Eigen::Map<MatrixType, 0, EigenDStride>;
|
||||
template <typename MatrixType>
|
||||
using EigenDRef = Eigen::Ref<MatrixType, 0, EigenDStride>;
|
||||
template <typename MatrixType>
|
||||
using EigenDMap = Eigen::Map<MatrixType, 0, EigenDStride>;
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
#if EIGEN_VERSION_AT_LEAST(3,3,0)
|
||||
#if EIGEN_VERSION_AT_LEAST(3, 3, 0)
|
||||
using EigenIndex = Eigen::Index;
|
||||
template <typename Scalar, int Flags, typename StorageIndex>
|
||||
using EigenMapSparseMatrix = Eigen::Map<Eigen::SparseMatrix<Scalar, Flags, StorageIndex>>;
|
||||
#else
|
||||
using EigenIndex = EIGEN_DEFAULT_DENSE_INDEX_TYPE;
|
||||
template <typename Scalar, int Flags, typename StorageIndex>
|
||||
using EigenMapSparseMatrix = Eigen::MappedSparseMatrix<Scalar, Flags, StorageIndex>;
|
||||
#endif
|
||||
|
||||
// Matches Eigen::Map, Eigen::Ref, blocks, etc:
|
||||
template <typename T> using is_eigen_dense_map = all_of<is_template_base_of<Eigen::DenseBase, T>, std::is_base_of<Eigen::MapBase<T, Eigen::ReadOnlyAccessors>, T>>;
|
||||
template <typename T> using is_eigen_mutable_map = std::is_base_of<Eigen::MapBase<T, Eigen::WriteAccessors>, T>;
|
||||
template <typename T> using is_eigen_dense_plain = all_of<negation<is_eigen_dense_map<T>>, is_template_base_of<Eigen::PlainObjectBase, T>>;
|
||||
template <typename T> using is_eigen_sparse = is_template_base_of<Eigen::SparseMatrixBase, T>;
|
||||
template <typename T>
|
||||
using is_eigen_dense_map = all_of<is_template_base_of<Eigen::DenseBase, T>,
|
||||
std::is_base_of<Eigen::MapBase<T, Eigen::ReadOnlyAccessors>, T>>;
|
||||
template <typename T>
|
||||
using is_eigen_mutable_map = std::is_base_of<Eigen::MapBase<T, Eigen::WriteAccessors>, T>;
|
||||
template <typename T>
|
||||
using is_eigen_dense_plain
|
||||
= all_of<negation<is_eigen_dense_map<T>>, is_template_base_of<Eigen::PlainObjectBase, T>>;
|
||||
template <typename T>
|
||||
using is_eigen_sparse = is_template_base_of<Eigen::SparseMatrixBase, T>;
|
||||
// Test for objects inheriting from EigenBase<Derived> that aren't captured by the above. This
|
||||
// basically covers anything that can be assigned to a dense matrix but that don't have a typical
|
||||
// matrix data layout that can be copied from their .data(). For example, DiagonalMatrix and
|
||||
// SelfAdjointView fall into this category.
|
||||
template <typename T> using is_eigen_other = all_of<
|
||||
is_template_base_of<Eigen::EigenBase, T>,
|
||||
negation<any_of<is_eigen_dense_map<T>, is_eigen_dense_plain<T>, is_eigen_sparse<T>>>
|
||||
>;
|
||||
template <typename T>
|
||||
using is_eigen_other
|
||||
= all_of<is_template_base_of<Eigen::EigenBase, T>,
|
||||
negation<any_of<is_eigen_dense_map<T>, is_eigen_dense_plain<T>, is_eigen_sparse<T>>>>;
|
||||
|
||||
// Captures numpy/eigen conformability status (returned by EigenProps::conformable()):
|
||||
template <bool EigenRowMajor> struct EigenConformable {
|
||||
template <bool EigenRowMajor>
|
||||
struct EigenConformable {
|
||||
bool conformable = false;
|
||||
EigenIndex rows = 0, cols = 0;
|
||||
EigenDStride stride{0, 0}; // Only valid if negativestrides is false!
|
||||
bool negativestrides = false; // If true, do not use stride!
|
||||
EigenDStride stride{0, 0}; // Only valid if negativestrides is false!
|
||||
bool negativestrides = false; // If true, do not use stride!
|
||||
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
EigenConformable(bool fits = false) : conformable{fits} {}
|
||||
// Matrix type:
|
||||
EigenConformable(EigenIndex r, EigenIndex c,
|
||||
EigenIndex rstride, EigenIndex cstride) :
|
||||
conformable{true}, rows{r}, cols{c} {
|
||||
// TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity. http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747
|
||||
if (rstride < 0 || cstride < 0) {
|
||||
negativestrides = true;
|
||||
} else {
|
||||
stride = {EigenRowMajor ? rstride : cstride /* outer stride */,
|
||||
EigenRowMajor ? cstride : rstride /* inner stride */ };
|
||||
}
|
||||
}
|
||||
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex rstride, EigenIndex cstride)
|
||||
: conformable{true}, rows{r}, cols{c},
|
||||
// TODO: when Eigen bug #747 is fixed, remove the tests for non-negativity.
|
||||
// http://eigen.tuxfamily.org/bz/show_bug.cgi?id=747
|
||||
stride{EigenRowMajor ? (rstride > 0 ? rstride : 0)
|
||||
: (cstride > 0 ? cstride : 0) /* outer stride */,
|
||||
EigenRowMajor ? (cstride > 0 ? cstride : 0)
|
||||
: (rstride > 0 ? rstride : 0) /* inner stride */},
|
||||
negativestrides{rstride < 0 || cstride < 0} {}
|
||||
// Vector type:
|
||||
EigenConformable(EigenIndex r, EigenIndex c, EigenIndex stride)
|
||||
: EigenConformable(r, c, r == 1 ? c*stride : stride, c == 1 ? r : r*stride) {}
|
||||
: EigenConformable(r, c, r == 1 ? c * stride : stride, c == 1 ? r : r * stride) {}
|
||||
|
||||
template <typename props> bool stride_compatible() const {
|
||||
template <typename props>
|
||||
bool stride_compatible() const {
|
||||
// To have compatible strides, we need (on both dimensions) one of fully dynamic strides,
|
||||
// matching strides, or a dimension size of 1 (in which case the stride value is irrelevant)
|
||||
return
|
||||
!negativestrides &&
|
||||
(props::inner_stride == Eigen::Dynamic || props::inner_stride == stride.inner() ||
|
||||
(EigenRowMajor ? cols : rows) == 1) &&
|
||||
(props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer() ||
|
||||
(EigenRowMajor ? rows : cols) == 1);
|
||||
// matching strides, or a dimension size of 1 (in which case the stride value is
|
||||
// irrelevant). Alternatively, if any dimension size is 0, the strides are not relevant
|
||||
// (and numpy ≥ 1.23 sets the strides to 0 in that case, so we need to check explicitly).
|
||||
if (negativestrides) {
|
||||
return false;
|
||||
}
|
||||
if (rows == 0 || cols == 0) {
|
||||
return true;
|
||||
}
|
||||
return (props::inner_stride == Eigen::Dynamic || props::inner_stride == stride.inner()
|
||||
|| (EigenRowMajor ? cols : rows) == 1)
|
||||
&& (props::outer_stride == Eigen::Dynamic || props::outer_stride == stride.outer()
|
||||
|| (EigenRowMajor ? rows : cols) == 1);
|
||||
}
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator bool() const { return conformable; }
|
||||
};
|
||||
|
||||
template <typename Type> struct eigen_extract_stride { using type = Type; };
|
||||
template <typename Type>
|
||||
struct eigen_extract_stride {
|
||||
using type = Type;
|
||||
};
|
||||
template <typename PlainObjectType, int MapOptions, typename StrideType>
|
||||
struct eigen_extract_stride<Eigen::Map<PlainObjectType, MapOptions, StrideType>> { using type = StrideType; };
|
||||
struct eigen_extract_stride<Eigen::Map<PlainObjectType, MapOptions, StrideType>> {
|
||||
using type = StrideType;
|
||||
};
|
||||
template <typename PlainObjectType, int Options, typename StrideType>
|
||||
struct eigen_extract_stride<Eigen::Ref<PlainObjectType, Options, StrideType>> { using type = StrideType; };
|
||||
struct eigen_extract_stride<Eigen::Ref<PlainObjectType, Options, StrideType>> {
|
||||
using type = StrideType;
|
||||
};
|
||||
|
||||
// Helper struct for extracting information from an Eigen type
|
||||
template <typename Type_> struct EigenProps {
|
||||
template <typename Type_>
|
||||
struct EigenProps {
|
||||
using Type = Type_;
|
||||
using Scalar = typename Type::Scalar;
|
||||
using StrideType = typename eigen_extract_stride<Type>::type;
|
||||
static constexpr EigenIndex
|
||||
rows = Type::RowsAtCompileTime,
|
||||
cols = Type::ColsAtCompileTime,
|
||||
size = Type::SizeAtCompileTime;
|
||||
static constexpr bool
|
||||
row_major = Type::IsRowMajor,
|
||||
vector = Type::IsVectorAtCompileTime, // At least one dimension has fixed size 1
|
||||
fixed_rows = rows != Eigen::Dynamic,
|
||||
fixed_cols = cols != Eigen::Dynamic,
|
||||
fixed = size != Eigen::Dynamic, // Fully-fixed size
|
||||
dynamic = !fixed_rows && !fixed_cols; // Fully-dynamic size
|
||||
static constexpr EigenIndex rows = Type::RowsAtCompileTime, cols = Type::ColsAtCompileTime,
|
||||
size = Type::SizeAtCompileTime;
|
||||
static constexpr bool row_major = Type::IsRowMajor,
|
||||
vector
|
||||
= Type::IsVectorAtCompileTime, // At least one dimension has fixed size 1
|
||||
fixed_rows = rows != Eigen::Dynamic, fixed_cols = cols != Eigen::Dynamic,
|
||||
fixed = size != Eigen::Dynamic, // Fully-fixed size
|
||||
dynamic = !fixed_rows && !fixed_cols; // Fully-dynamic size
|
||||
|
||||
template <EigenIndex i, EigenIndex ifzero> using if_zero = std::integral_constant<EigenIndex, i == 0 ? ifzero : i>;
|
||||
static constexpr EigenIndex inner_stride = if_zero<StrideType::InnerStrideAtCompileTime, 1>::value,
|
||||
outer_stride = if_zero<StrideType::OuterStrideAtCompileTime,
|
||||
vector ? size : row_major ? cols : rows>::value;
|
||||
static constexpr bool dynamic_stride = inner_stride == Eigen::Dynamic && outer_stride == Eigen::Dynamic;
|
||||
static constexpr bool requires_row_major = !dynamic_stride && !vector && (row_major ? inner_stride : outer_stride) == 1;
|
||||
static constexpr bool requires_col_major = !dynamic_stride && !vector && (row_major ? outer_stride : inner_stride) == 1;
|
||||
template <EigenIndex i, EigenIndex ifzero>
|
||||
using if_zero = std::integral_constant<EigenIndex, i == 0 ? ifzero : i>;
|
||||
static constexpr EigenIndex inner_stride
|
||||
= if_zero<StrideType::InnerStrideAtCompileTime, 1>::value,
|
||||
outer_stride = if_zero < StrideType::OuterStrideAtCompileTime,
|
||||
vector ? size
|
||||
: row_major ? cols
|
||||
: rows > ::value;
|
||||
static constexpr bool dynamic_stride
|
||||
= inner_stride == Eigen::Dynamic && outer_stride == Eigen::Dynamic;
|
||||
static constexpr bool requires_row_major
|
||||
= !dynamic_stride && !vector && (row_major ? inner_stride : outer_stride) == 1;
|
||||
static constexpr bool requires_col_major
|
||||
= !dynamic_stride && !vector && (row_major ? outer_stride : inner_stride) == 1;
|
||||
|
||||
// Takes an input array and determines whether we can make it fit into the Eigen type. If
|
||||
// the array is a vector, we attempt to fit it into either an Eigen 1xN or Nx1 vector
|
||||
// (preferring the latter if it will fit in either, i.e. for a fully dynamic matrix type).
|
||||
static EigenConformable<row_major> conformable(const array &a) {
|
||||
const auto dims = a.ndim();
|
||||
if (dims < 1 || dims > 2)
|
||||
if (dims < 1 || dims > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dims == 2) { // Matrix type: require exact match (or dynamic)
|
||||
|
||||
EigenIndex
|
||||
np_rows = a.shape(0),
|
||||
np_cols = a.shape(1),
|
||||
np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
|
||||
np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar));
|
||||
if ((fixed_rows && np_rows != rows) || (fixed_cols && np_cols != cols))
|
||||
EigenIndex np_rows = a.shape(0), np_cols = a.shape(1),
|
||||
np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
|
||||
np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar));
|
||||
if ((PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && np_rows != rows)
|
||||
|| (PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return {np_rows, np_cols, np_rstride, np_cstride};
|
||||
}
|
||||
|
||||
// Otherwise we're storing an n-vector. Only one of the strides will be used, but whichever
|
||||
// is used, we want the (single) numpy stride value.
|
||||
// Otherwise we're storing an n-vector. Only one of the strides will be used, but
|
||||
// whichever is used, we want the (single) numpy stride value.
|
||||
const EigenIndex n = a.shape(0),
|
||||
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
|
||||
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
|
||||
|
||||
if (vector) { // Eigen type is a compile-time vector
|
||||
if (fixed && size != n)
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(fixed) && size != n) {
|
||||
return false; // Vector size mismatch
|
||||
}
|
||||
return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
|
||||
}
|
||||
else if (fixed) {
|
||||
if (fixed) {
|
||||
// The type has a fixed size, but is not a vector: abort
|
||||
return false;
|
||||
}
|
||||
else if (fixed_cols) {
|
||||
if (fixed_cols) {
|
||||
// Since this isn't a vector, cols must be != 1. We allow this only if it exactly
|
||||
// equals the number of elements (rows is Dynamic, and so 1 row is allowed).
|
||||
if (cols != n) return false;
|
||||
if (cols != n) {
|
||||
return false;
|
||||
}
|
||||
return {1, n, stride};
|
||||
} // Otherwise it's either fully dynamic, or column dynamic; both become a column vector
|
||||
if (PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && rows != n) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// Otherwise it's either fully dynamic, or column dynamic; both become a column vector
|
||||
if (fixed_rows && rows != n) return false;
|
||||
return {n, 1, stride};
|
||||
}
|
||||
return {n, 1, stride};
|
||||
}
|
||||
|
||||
static constexpr bool show_writeable = is_eigen_dense_map<Type>::value && is_eigen_mutable_map<Type>::value;
|
||||
static constexpr bool show_writeable
|
||||
= is_eigen_dense_map<Type>::value && is_eigen_mutable_map<Type>::value;
|
||||
static constexpr bool show_order = is_eigen_dense_map<Type>::value;
|
||||
static constexpr bool show_c_contiguous = show_order && requires_row_major;
|
||||
static constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;
|
||||
static constexpr bool show_f_contiguous
|
||||
= !show_c_contiguous && show_order && requires_col_major;
|
||||
|
||||
static constexpr auto descriptor =
|
||||
_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name +
|
||||
_("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) +
|
||||
_(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) +
|
||||
_("]") +
|
||||
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be
|
||||
// satisfied: writeable=True (for a mutable reference), and, depending on the map's stride
|
||||
// options, possibly f_contiguous or c_contiguous. We include them in the descriptor output
|
||||
// to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to
|
||||
// see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you
|
||||
// *gave* a numpy.ndarray of the right type and dimensions.
|
||||
_<show_writeable>(", flags.writeable", "") +
|
||||
_<show_c_contiguous>(", flags.c_contiguous", "") +
|
||||
_<show_f_contiguous>(", flags.f_contiguous", "") +
|
||||
_("]");
|
||||
static constexpr auto descriptor
|
||||
= const_name("numpy.ndarray[") + npy_format_descriptor<Scalar>::name + const_name("[")
|
||||
+ const_name<fixed_rows>(const_name<(size_t) rows>(), const_name("m")) + const_name(", ")
|
||||
+ const_name<fixed_cols>(const_name<(size_t) cols>(), const_name("n")) + const_name("]")
|
||||
+
|
||||
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to
|
||||
// be satisfied: writeable=True (for a mutable reference), and, depending on the map's
|
||||
// stride options, possibly f_contiguous or c_contiguous. We include them in the
|
||||
// descriptor output to provide some hint as to why a TypeError is occurring (otherwise
|
||||
// it can be confusing to see that a function accepts a 'numpy.ndarray[float64[3,2]]' and
|
||||
// an error message that you *gave* a numpy.ndarray of the right type and dimensions.
|
||||
const_name<show_writeable>(", flags.writeable", "")
|
||||
+ const_name<show_c_contiguous>(", flags.c_contiguous", "")
|
||||
+ const_name<show_f_contiguous>(", flags.f_contiguous", "") + const_name("]");
|
||||
};
|
||||
|
||||
// Casts an Eigen type to numpy array. If given a base, the numpy array references the src data,
|
||||
// otherwise it'll make a copy. writeable lets you turn off the writeable flag for the array.
|
||||
template <typename props> handle eigen_array_cast(typename props::Type const &src, handle base = handle(), bool writeable = true) {
|
||||
template <typename props>
|
||||
handle
|
||||
eigen_array_cast(typename props::Type const &src, handle base = handle(), bool writeable = true) {
|
||||
constexpr ssize_t elem_size = sizeof(typename props::Scalar);
|
||||
array a;
|
||||
if (props::vector)
|
||||
a = array({ src.size() }, { elem_size * src.innerStride() }, src.data(), base);
|
||||
else
|
||||
a = array({ src.rows(), src.cols() }, { elem_size * src.rowStride(), elem_size * src.colStride() },
|
||||
src.data(), base);
|
||||
if (props::vector) {
|
||||
a = array({src.size()}, {elem_size * src.innerStride()}, src.data(), base);
|
||||
} else {
|
||||
a = array({src.rows(), src.cols()},
|
||||
{elem_size * src.rowStride(), elem_size * src.colStride()},
|
||||
src.data(),
|
||||
base);
|
||||
}
|
||||
|
||||
if (!writeable)
|
||||
if (!writeable) {
|
||||
array_proxy(a.ptr())->flags &= ~detail::npy_api::NPY_ARRAY_WRITEABLE_;
|
||||
}
|
||||
|
||||
return a.release();
|
||||
}
|
||||
@ -236,10 +284,10 @@ handle eigen_ref_array(Type &src, handle parent = none()) {
|
||||
return eigen_array_cast<props>(src, parent, !std::is_const<Type>::value);
|
||||
}
|
||||
|
||||
// Takes a pointer to some dense, plain Eigen type, builds a capsule around it, then returns a numpy
|
||||
// array that references the encapsulated data with a python-side reference to the capsule to tie
|
||||
// its destruction to that of any dependent python objects. Const-ness is determined by whether or
|
||||
// not the Type of the pointer given is const.
|
||||
// Takes a pointer to some dense, plain Eigen type, builds a capsule around it, then returns a
|
||||
// numpy array that references the encapsulated data with a python-side reference to the capsule to
|
||||
// tie its destruction to that of any dependent python objects. Const-ness is determined by
|
||||
// whether or not the Type of the pointer given is const.
|
||||
template <typename props, typename Type, typename = enable_if_t<is_eigen_dense_plain<Type>::value>>
|
||||
handle eigen_encapsulate(Type *src) {
|
||||
capsule base(src, [](void *o) { delete static_cast<Type *>(o); });
|
||||
@ -248,35 +296,42 @@ handle eigen_encapsulate(Type *src) {
|
||||
|
||||
// Type caster for regular, dense matrix types (e.g. MatrixXd), but not maps/refs/etc. of dense
|
||||
// types.
|
||||
template<typename Type>
|
||||
template <typename Type>
|
||||
struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
|
||||
using Scalar = typename Type::Scalar;
|
||||
using props = EigenProps<Type>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
// If we're in no-convert mode, only load if given an array of the correct type
|
||||
if (!convert && !isinstance<array_t<Scalar>>(src))
|
||||
if (!convert && !isinstance<array_t<Scalar>>(src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Coerce into an array, but don't do type conversion yet; the copy below handles it.
|
||||
auto buf = array::ensure(src);
|
||||
|
||||
if (!buf)
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto dims = buf.ndim();
|
||||
if (dims < 1 || dims > 2)
|
||||
if (dims < 1 || dims > 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fits = props::conformable(buf);
|
||||
if (!fits)
|
||||
if (!fits) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate the new type, then build a numpy reference into it
|
||||
value = Type(fits.rows, fits.cols);
|
||||
auto ref = reinterpret_steal<array>(eigen_ref_array<props>(value));
|
||||
if (dims == 1) ref = ref.squeeze();
|
||||
else if (ref.ndim() == 1) buf = buf.squeeze();
|
||||
if (dims == 1) {
|
||||
ref = ref.squeeze();
|
||||
} else if (ref.ndim() == 1) {
|
||||
buf = buf.squeeze();
|
||||
}
|
||||
|
||||
int result = detail::npy_api::get().PyArray_CopyInto_(ref.ptr(), buf.ptr());
|
||||
|
||||
@ -289,7 +344,6 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Cast implementation
|
||||
template <typename CType>
|
||||
static handle cast_impl(CType *src, return_value_policy policy, handle parent) {
|
||||
@ -312,7 +366,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// Normal returned non-reference, non-const value:
|
||||
static handle cast(Type &&src, return_value_policy /* policy */, handle parent) {
|
||||
return cast_impl(&src, return_value_policy::move, parent);
|
||||
@ -323,14 +376,18 @@ public:
|
||||
}
|
||||
// lvalue reference return; default (automatic) becomes copy
|
||||
static handle cast(Type &src, return_value_policy policy, handle parent) {
|
||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||
if (policy == return_value_policy::automatic
|
||||
|| policy == return_value_policy::automatic_reference) {
|
||||
policy = return_value_policy::copy;
|
||||
}
|
||||
return cast_impl(&src, policy, parent);
|
||||
}
|
||||
// const lvalue reference return; default (automatic) becomes copy
|
||||
static handle cast(const Type &src, return_value_policy policy, handle parent) {
|
||||
if (policy == return_value_policy::automatic || policy == return_value_policy::automatic_reference)
|
||||
if (policy == return_value_policy::automatic
|
||||
|| policy == return_value_policy::automatic_reference) {
|
||||
policy = return_value_policy::copy;
|
||||
}
|
||||
return cast(&src, policy, parent);
|
||||
}
|
||||
// non-const pointer return
|
||||
@ -344,28 +401,32 @@ public:
|
||||
|
||||
static constexpr auto name = props::descriptor;
|
||||
|
||||
operator Type*() { return &value; }
|
||||
operator Type&() { return value; }
|
||||
operator Type&&() && { return std::move(value); }
|
||||
template <typename T> using cast_op_type = movable_cast_op_type<T>;
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator Type *() { return &value; }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator Type &() { return value; }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator Type &&() && { return std::move(value); }
|
||||
template <typename T>
|
||||
using cast_op_type = movable_cast_op_type<T>;
|
||||
|
||||
private:
|
||||
Type value;
|
||||
};
|
||||
|
||||
// Base class for casting reference/map/block/etc. objects back to python.
|
||||
template <typename MapType> struct eigen_map_caster {
|
||||
template <typename MapType>
|
||||
struct eigen_map_caster {
|
||||
private:
|
||||
using props = EigenProps<MapType>;
|
||||
|
||||
public:
|
||||
|
||||
// Directly referencing a ref/map's data is a bit dangerous (whatever the map/ref points to has
|
||||
// to stay around), but we'll allow it under the assumption that you know what you're doing (and
|
||||
// have an appropriate keep_alive in place). We return a numpy array pointing directly at the
|
||||
// ref's data (The numpy array ends up read-only if the ref was to a const matrix type.) Note
|
||||
// that this means you need to ensure you don't destroy the object in some other way (e.g. with
|
||||
// an appropriate keep_alive, or with a reference to a statically allocated matrix).
|
||||
// to stay around), but we'll allow it under the assumption that you know what you're doing
|
||||
// (and have an appropriate keep_alive in place). We return a numpy array pointing directly at
|
||||
// the ref's data (The numpy array ends up read-only if the ref was to a const matrix type.)
|
||||
// Note that this means you need to ensure you don't destroy the object in some other way (e.g.
|
||||
// with an appropriate keep_alive, or with a reference to a statically allocated matrix).
|
||||
static handle cast(const MapType &src, return_value_policy policy, handle parent) {
|
||||
switch (policy) {
|
||||
case return_value_policy::copy:
|
||||
@ -389,43 +450,50 @@ public:
|
||||
// you end up here if you try anyway.
|
||||
bool load(handle, bool) = delete;
|
||||
operator MapType() = delete;
|
||||
template <typename> using cast_op_type = MapType;
|
||||
template <typename>
|
||||
using cast_op_type = MapType;
|
||||
};
|
||||
|
||||
// We can return any map-like object (but can only load Refs, specialized next):
|
||||
template <typename Type> struct type_caster<Type, enable_if_t<is_eigen_dense_map<Type>::value>>
|
||||
: eigen_map_caster<Type> {};
|
||||
template <typename Type>
|
||||
struct type_caster<Type, enable_if_t<is_eigen_dense_map<Type>::value>> : eigen_map_caster<Type> {};
|
||||
|
||||
// Loader for Ref<...> arguments. See the documentation for info on how to make this work without
|
||||
// copying (it requires some extra effort in many cases).
|
||||
template <typename PlainObjectType, typename StrideType>
|
||||
struct type_caster<
|
||||
Eigen::Ref<PlainObjectType, 0, StrideType>,
|
||||
enable_if_t<is_eigen_dense_map<Eigen::Ref<PlainObjectType, 0, StrideType>>::value>
|
||||
> : public eigen_map_caster<Eigen::Ref<PlainObjectType, 0, StrideType>> {
|
||||
enable_if_t<is_eigen_dense_map<Eigen::Ref<PlainObjectType, 0, StrideType>>::value>>
|
||||
: public eigen_map_caster<Eigen::Ref<PlainObjectType, 0, StrideType>> {
|
||||
private:
|
||||
using Type = Eigen::Ref<PlainObjectType, 0, StrideType>;
|
||||
using props = EigenProps<Type>;
|
||||
using Scalar = typename props::Scalar;
|
||||
using MapType = Eigen::Map<PlainObjectType, 0, StrideType>;
|
||||
using Array = array_t<Scalar, array::forcecast |
|
||||
((props::row_major ? props::inner_stride : props::outer_stride) == 1 ? array::c_style :
|
||||
(props::row_major ? props::outer_stride : props::inner_stride) == 1 ? array::f_style : 0)>;
|
||||
using Array
|
||||
= array_t<Scalar,
|
||||
array::forcecast
|
||||
| ((props::row_major ? props::inner_stride : props::outer_stride) == 1
|
||||
? array::c_style
|
||||
: (props::row_major ? props::outer_stride : props::inner_stride) == 1
|
||||
? array::f_style
|
||||
: 0)>;
|
||||
static constexpr bool need_writeable = is_eigen_mutable_map<Type>::value;
|
||||
// Delay construction (these have no default constructor)
|
||||
std::unique_ptr<MapType> map;
|
||||
std::unique_ptr<Type> ref;
|
||||
// Our array. When possible, this is just a numpy array pointing to the source data, but
|
||||
// sometimes we can't avoid copying (e.g. input is not a numpy array at all, has an incompatible
|
||||
// layout, or is an array of a type that needs to be converted). Using a numpy temporary
|
||||
// (rather than an Eigen temporary) saves an extra copy when we need both type conversion and
|
||||
// storage order conversion. (Note that we refuse to use this temporary copy when loading an
|
||||
// argument for a Ref<M> with M non-const, i.e. a read-write reference).
|
||||
// sometimes we can't avoid copying (e.g. input is not a numpy array at all, has an
|
||||
// incompatible layout, or is an array of a type that needs to be converted). Using a numpy
|
||||
// temporary (rather than an Eigen temporary) saves an extra copy when we need both type
|
||||
// conversion and storage order conversion. (Note that we refuse to use this temporary copy
|
||||
// when loading an argument for a Ref<M> with M non-const, i.e. a read-write reference).
|
||||
Array copy_or_ref;
|
||||
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
// First check whether what we have is already an array of the right type. If not, we can't
|
||||
// avoid a copy (because the copy is also going to do type conversion).
|
||||
// First check whether what we have is already an array of the right type. If not, we
|
||||
// can't avoid a copy (because the copy is also going to do type conversion).
|
||||
bool need_copy = !isinstance<Array>(src);
|
||||
|
||||
EigenConformable<props::row_major> fits;
|
||||
@ -436,13 +504,15 @@ public:
|
||||
|
||||
if (aref && (!need_writeable || aref.writeable())) {
|
||||
fits = props::conformable(aref);
|
||||
if (!fits) return false; // Incompatible dimensions
|
||||
if (!fits.template stride_compatible<props>())
|
||||
if (!fits) {
|
||||
return false; // Incompatible dimensions
|
||||
}
|
||||
if (!fits.template stride_compatible<props>()) {
|
||||
need_copy = true;
|
||||
else
|
||||
} else {
|
||||
copy_or_ref = std::move(aref);
|
||||
}
|
||||
else {
|
||||
}
|
||||
} else {
|
||||
need_copy = true;
|
||||
}
|
||||
}
|
||||
@ -451,64 +521,93 @@ public:
|
||||
// We need to copy: If we need a mutable reference, or we're not supposed to convert
|
||||
// (either because we're in the no-convert overload pass, or because we're explicitly
|
||||
// instructed not to copy (via `py::arg().noconvert()`) we have to fail loading.
|
||||
if (!convert || need_writeable) return false;
|
||||
if (!convert || need_writeable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Array copy = Array::ensure(src);
|
||||
if (!copy) return false;
|
||||
fits = props::conformable(copy);
|
||||
if (!fits || !fits.template stride_compatible<props>())
|
||||
if (!copy) {
|
||||
return false;
|
||||
}
|
||||
fits = props::conformable(copy);
|
||||
if (!fits || !fits.template stride_compatible<props>()) {
|
||||
return false;
|
||||
}
|
||||
copy_or_ref = std::move(copy);
|
||||
loader_life_support::add_patient(copy_or_ref);
|
||||
}
|
||||
|
||||
ref.reset();
|
||||
map.reset(new MapType(data(copy_or_ref), fits.rows, fits.cols, make_stride(fits.stride.outer(), fits.stride.inner())));
|
||||
map.reset(new MapType(data(copy_or_ref),
|
||||
fits.rows,
|
||||
fits.cols,
|
||||
make_stride(fits.stride.outer(), fits.stride.inner())));
|
||||
ref.reset(new Type(*map));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
operator Type*() { return ref.get(); }
|
||||
operator Type&() { return *ref; }
|
||||
template <typename _T> using cast_op_type = pybind11::detail::cast_op_type<_T>;
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator Type *() { return ref.get(); }
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
operator Type &() { return *ref; }
|
||||
template <typename _T>
|
||||
using cast_op_type = pybind11::detail::cast_op_type<_T>;
|
||||
|
||||
private:
|
||||
template <typename T = Type, enable_if_t<is_eigen_mutable_map<T>::value, int> = 0>
|
||||
Scalar *data(Array &a) { return a.mutable_data(); }
|
||||
Scalar *data(Array &a) {
|
||||
return a.mutable_data();
|
||||
}
|
||||
|
||||
template <typename T = Type, enable_if_t<!is_eigen_mutable_map<T>::value, int> = 0>
|
||||
const Scalar *data(Array &a) { return a.data(); }
|
||||
const Scalar *data(Array &a) {
|
||||
return a.data();
|
||||
}
|
||||
|
||||
// Attempt to figure out a constructor of `Stride` that will work.
|
||||
// If both strides are fixed, use a default constructor:
|
||||
template <typename S> using stride_ctor_default = bool_constant<
|
||||
S::InnerStrideAtCompileTime != Eigen::Dynamic && S::OuterStrideAtCompileTime != Eigen::Dynamic &&
|
||||
std::is_default_constructible<S>::value>;
|
||||
template <typename S>
|
||||
using stride_ctor_default = bool_constant<S::InnerStrideAtCompileTime != Eigen::Dynamic
|
||||
&& S::OuterStrideAtCompileTime != Eigen::Dynamic
|
||||
&& std::is_default_constructible<S>::value>;
|
||||
// Otherwise, if there is a two-index constructor, assume it is (outer,inner) like
|
||||
// Eigen::Stride, and use it:
|
||||
template <typename S> using stride_ctor_dual = bool_constant<
|
||||
!stride_ctor_default<S>::value && std::is_constructible<S, EigenIndex, EigenIndex>::value>;
|
||||
template <typename S>
|
||||
using stride_ctor_dual
|
||||
= bool_constant<!stride_ctor_default<S>::value
|
||||
&& std::is_constructible<S, EigenIndex, EigenIndex>::value>;
|
||||
// Otherwise, if there is a one-index constructor, and just one of the strides is dynamic, use
|
||||
// it (passing whichever stride is dynamic).
|
||||
template <typename S> using stride_ctor_outer = bool_constant<
|
||||
!any_of<stride_ctor_default<S>, stride_ctor_dual<S>>::value &&
|
||||
S::OuterStrideAtCompileTime == Eigen::Dynamic && S::InnerStrideAtCompileTime != Eigen::Dynamic &&
|
||||
std::is_constructible<S, EigenIndex>::value>;
|
||||
template <typename S> using stride_ctor_inner = bool_constant<
|
||||
!any_of<stride_ctor_default<S>, stride_ctor_dual<S>>::value &&
|
||||
S::InnerStrideAtCompileTime == Eigen::Dynamic && S::OuterStrideAtCompileTime != Eigen::Dynamic &&
|
||||
std::is_constructible<S, EigenIndex>::value>;
|
||||
template <typename S>
|
||||
using stride_ctor_outer
|
||||
= bool_constant<!any_of<stride_ctor_default<S>, stride_ctor_dual<S>>::value
|
||||
&& S::OuterStrideAtCompileTime == Eigen::Dynamic
|
||||
&& S::InnerStrideAtCompileTime != Eigen::Dynamic
|
||||
&& std::is_constructible<S, EigenIndex>::value>;
|
||||
template <typename S>
|
||||
using stride_ctor_inner
|
||||
= bool_constant<!any_of<stride_ctor_default<S>, stride_ctor_dual<S>>::value
|
||||
&& S::InnerStrideAtCompileTime == Eigen::Dynamic
|
||||
&& S::OuterStrideAtCompileTime != Eigen::Dynamic
|
||||
&& std::is_constructible<S, EigenIndex>::value>;
|
||||
|
||||
template <typename S = StrideType, enable_if_t<stride_ctor_default<S>::value, int> = 0>
|
||||
static S make_stride(EigenIndex, EigenIndex) { return S(); }
|
||||
static S make_stride(EigenIndex, EigenIndex) {
|
||||
return S();
|
||||
}
|
||||
template <typename S = StrideType, enable_if_t<stride_ctor_dual<S>::value, int> = 0>
|
||||
static S make_stride(EigenIndex outer, EigenIndex inner) { return S(outer, inner); }
|
||||
static S make_stride(EigenIndex outer, EigenIndex inner) {
|
||||
return S(outer, inner);
|
||||
}
|
||||
template <typename S = StrideType, enable_if_t<stride_ctor_outer<S>::value, int> = 0>
|
||||
static S make_stride(EigenIndex outer, EigenIndex) { return S(outer); }
|
||||
static S make_stride(EigenIndex outer, EigenIndex) {
|
||||
return S(outer);
|
||||
}
|
||||
template <typename S = StrideType, enable_if_t<stride_ctor_inner<S>::value, int> = 0>
|
||||
static S make_stride(EigenIndex, EigenIndex inner) { return S(inner); }
|
||||
|
||||
static S make_stride(EigenIndex, EigenIndex inner) {
|
||||
return S(inner);
|
||||
}
|
||||
};
|
||||
|
||||
// type_caster for special matrix types (e.g. DiagonalMatrix), which are EigenBase, but not
|
||||
@ -518,14 +617,18 @@ private:
|
||||
template <typename Type>
|
||||
struct type_caster<Type, enable_if_t<is_eigen_other<Type>::value>> {
|
||||
protected:
|
||||
using Matrix = Eigen::Matrix<typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime>;
|
||||
using Matrix
|
||||
= Eigen::Matrix<typename Type::Scalar, Type::RowsAtCompileTime, Type::ColsAtCompileTime>;
|
||||
using props = EigenProps<Matrix>;
|
||||
|
||||
public:
|
||||
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
|
||||
handle h = eigen_encapsulate<props>(new Matrix(src));
|
||||
return h;
|
||||
}
|
||||
static handle cast(const Type *src, return_value_policy policy, handle parent) { return cast(*src, policy, parent); }
|
||||
static handle cast(const Type *src, return_value_policy policy, handle parent) {
|
||||
return cast(*src, policy, parent);
|
||||
}
|
||||
|
||||
static constexpr auto name = props::descriptor;
|
||||
|
||||
@ -534,10 +637,11 @@ public:
|
||||
// you end up here if you try anyway.
|
||||
bool load(handle, bool) = delete;
|
||||
operator Type() = delete;
|
||||
template <typename> using cast_op_type = Type;
|
||||
template <typename>
|
||||
using cast_op_type = Type;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
template <typename Type>
|
||||
struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
using Scalar = typename Type::Scalar;
|
||||
using StorageIndex = remove_reference_t<decltype(*std::declval<Type>().outerIndexPtr())>;
|
||||
@ -545,13 +649,13 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
static constexpr bool rowMajor = Type::IsRowMajor;
|
||||
|
||||
bool load(handle src, bool) {
|
||||
if (!src)
|
||||
if (!src) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto obj = reinterpret_borrow<object>(src);
|
||||
object sparse_module = module_::import("scipy.sparse");
|
||||
object matrix_type = sparse_module.attr(
|
||||
rowMajor ? "csr_matrix" : "csc_matrix");
|
||||
object matrix_type = sparse_module.attr(rowMajor ? "csr_matrix" : "csc_matrix");
|
||||
|
||||
if (!type::handle_of(obj).is(matrix_type)) {
|
||||
try {
|
||||
@ -567,41 +671,43 @@ struct type_caster<Type, enable_if_t<is_eigen_sparse<Type>::value>> {
|
||||
auto shape = pybind11::tuple((pybind11::object) obj.attr("shape"));
|
||||
auto nnz = obj.attr("nnz").cast<Index>();
|
||||
|
||||
if (!values || !innerIndices || !outerIndices)
|
||||
if (!values || !innerIndices || !outerIndices) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = Eigen::MappedSparseMatrix<Scalar, Type::Flags, StorageIndex>(
|
||||
shape[0].cast<Index>(), shape[1].cast<Index>(), nnz,
|
||||
outerIndices.mutable_data(), innerIndices.mutable_data(), values.mutable_data());
|
||||
value = EigenMapSparseMatrix<Scalar,
|
||||
Type::Flags &(Eigen::RowMajor | Eigen::ColMajor),
|
||||
StorageIndex>(shape[0].cast<Index>(),
|
||||
shape[1].cast<Index>(),
|
||||
std::move(nnz),
|
||||
outerIndices.mutable_data(),
|
||||
innerIndices.mutable_data(),
|
||||
values.mutable_data());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static handle cast(const Type &src, return_value_policy /* policy */, handle /* parent */) {
|
||||
const_cast<Type&>(src).makeCompressed();
|
||||
const_cast<Type &>(src).makeCompressed();
|
||||
|
||||
object matrix_type = module_::import("scipy.sparse").attr(
|
||||
rowMajor ? "csr_matrix" : "csc_matrix");
|
||||
object matrix_type
|
||||
= module_::import("scipy.sparse").attr(rowMajor ? "csr_matrix" : "csc_matrix");
|
||||
|
||||
array data(src.nonZeros(), src.valuePtr());
|
||||
array outerIndices((rowMajor ? src.rows() : src.cols()) + 1, src.outerIndexPtr());
|
||||
array innerIndices(src.nonZeros(), src.innerIndexPtr());
|
||||
|
||||
return matrix_type(
|
||||
std::make_tuple(data, innerIndices, outerIndices),
|
||||
std::make_pair(src.rows(), src.cols())
|
||||
).release();
|
||||
return matrix_type(pybind11::make_tuple(
|
||||
std::move(data), std::move(innerIndices), std::move(outerIndices)),
|
||||
pybind11::make_tuple(src.rows(), src.cols()))
|
||||
.release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(Type, _<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[", "scipy.sparse.csc_matrix[")
|
||||
+ npy_format_descriptor<Scalar>::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(Type,
|
||||
const_name<(Type::IsRowMajor) != 0>("scipy.sparse.csr_matrix[",
|
||||
"scipy.sparse.csc_matrix[")
|
||||
+ npy_format_descriptor<Scalar>::name + const_name("]"));
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
||||
#if defined(__GNUG__) || defined(__clang__)
|
||||
# pragma GCC diagnostic pop
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
180
3rdparty/pybind11/include/pybind11/embed.h
vendored
180
3rdparty/pybind11/include/pybind11/embed.h
vendored
@ -12,23 +12,16 @@
|
||||
#include "pybind11.h"
|
||||
#include "eval.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#if defined(PYPY_VERSION)
|
||||
# error Embedding the interpreter is not supported with PyPy
|
||||
# error Embedding the interpreter is not supported with PyPy
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||
extern "C" PyObject *pybind11_init_impl_##name(); \
|
||||
extern "C" PyObject *pybind11_init_impl_##name() { \
|
||||
return pybind11_init_wrapper_##name(); \
|
||||
}
|
||||
#else
|
||||
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||
extern "C" void pybind11_init_impl_##name(); \
|
||||
extern "C" void pybind11_init_impl_##name() { \
|
||||
pybind11_init_wrapper_##name(); \
|
||||
}
|
||||
#endif
|
||||
#define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||
extern "C" PyObject *pybind11_init_impl_##name(); \
|
||||
extern "C" PyObject *pybind11_init_impl_##name() { return pybind11_init_wrapper_##name(); }
|
||||
|
||||
/** \rst
|
||||
Add a new module to the table of builtins for the interpreter. Must be
|
||||
@ -45,69 +38,143 @@
|
||||
});
|
||||
}
|
||||
\endrst */
|
||||
#define PYBIND11_EMBEDDED_MODULE(name, variable) \
|
||||
static ::pybind11::module_::module_def \
|
||||
PYBIND11_CONCAT(pybind11_module_def_, name); \
|
||||
static void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ &); \
|
||||
static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \
|
||||
auto m = ::pybind11::module_::create_extension_module( \
|
||||
PYBIND11_TOSTRING(name), nullptr, \
|
||||
&PYBIND11_CONCAT(pybind11_module_def_, name)); \
|
||||
try { \
|
||||
PYBIND11_CONCAT(pybind11_init_, name)(m); \
|
||||
return m.ptr(); \
|
||||
} PYBIND11_CATCH_INIT_EXCEPTIONS \
|
||||
} \
|
||||
PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||
::pybind11::detail::embedded_module PYBIND11_CONCAT(pybind11_module_, name) \
|
||||
(PYBIND11_TOSTRING(name), \
|
||||
PYBIND11_CONCAT(pybind11_init_impl_, name)); \
|
||||
void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ &variable)
|
||||
|
||||
#define PYBIND11_EMBEDDED_MODULE(name, variable) \
|
||||
static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name); \
|
||||
static void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ &); \
|
||||
static PyObject PYBIND11_CONCAT(*pybind11_init_wrapper_, name)() { \
|
||||
auto m = ::pybind11::module_::create_extension_module( \
|
||||
PYBIND11_TOSTRING(name), nullptr, &PYBIND11_CONCAT(pybind11_module_def_, name)); \
|
||||
try { \
|
||||
PYBIND11_CONCAT(pybind11_init_, name)(m); \
|
||||
return m.ptr(); \
|
||||
} \
|
||||
PYBIND11_CATCH_INIT_EXCEPTIONS \
|
||||
} \
|
||||
PYBIND11_EMBEDDED_MODULE_IMPL(name) \
|
||||
::pybind11::detail::embedded_module PYBIND11_CONCAT(pybind11_module_, name)( \
|
||||
PYBIND11_TOSTRING(name), PYBIND11_CONCAT(pybind11_init_impl_, name)); \
|
||||
void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ \
|
||||
& variable) // NOLINT(bugprone-macro-parentheses)
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
/// Python 2.7/3.x compatible version of `PyImport_AppendInittab` and error checks.
|
||||
struct embedded_module {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
using init_t = PyObject *(*)();
|
||||
#else
|
||||
using init_t = void (*)();
|
||||
#endif
|
||||
using init_t = PyObject *(*) ();
|
||||
embedded_module(const char *name, init_t init) {
|
||||
if (Py_IsInitialized())
|
||||
if (Py_IsInitialized() != 0) {
|
||||
pybind11_fail("Can't add new modules after the interpreter has been initialized");
|
||||
}
|
||||
|
||||
auto result = PyImport_AppendInittab(name, init);
|
||||
if (result == -1)
|
||||
if (result == -1) {
|
||||
pybind11_fail("Insufficient memory to add a new module");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct wide_char_arg_deleter {
|
||||
void operator()(wchar_t *ptr) const {
|
||||
// API docs: https://docs.python.org/3/c-api/sys.html#c.Py_DecodeLocale
|
||||
PyMem_RawFree(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
inline wchar_t *widen_chars(const char *safe_arg) {
|
||||
wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
|
||||
return widened_arg;
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
/** \rst
|
||||
Initialize the Python interpreter. No other pybind11 or CPython API functions can be
|
||||
called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The
|
||||
optional parameter can be used to skip the registration of signal handlers (see the
|
||||
`Python documentation`_ for details). Calling this function again after the interpreter
|
||||
has already been initialized is a fatal error.
|
||||
optional `init_signal_handlers` parameter can be used to skip the registration of
|
||||
signal handlers (see the `Python documentation`_ for details). Calling this function
|
||||
again after the interpreter has already been initialized is a fatal error.
|
||||
|
||||
If initializing the Python interpreter fails, then the program is terminated. (This
|
||||
is controlled by the CPython runtime and is an exception to pybind11's normal behavior
|
||||
of throwing exceptions on errors.)
|
||||
|
||||
The remaining optional parameters, `argc`, `argv`, and `add_program_dir_to_path` are
|
||||
used to populate ``sys.argv`` and ``sys.path``.
|
||||
See the |PySys_SetArgvEx documentation|_ for details.
|
||||
|
||||
.. _Python documentation: https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx
|
||||
.. |PySys_SetArgvEx documentation| replace:: ``PySys_SetArgvEx`` documentation
|
||||
.. _PySys_SetArgvEx documentation: https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
|
||||
\endrst */
|
||||
inline void initialize_interpreter(bool init_signal_handlers = true) {
|
||||
if (Py_IsInitialized())
|
||||
inline void initialize_interpreter(bool init_signal_handlers = true,
|
||||
int argc = 0,
|
||||
const char *const *argv = nullptr,
|
||||
bool add_program_dir_to_path = true) {
|
||||
if (Py_IsInitialized() != 0) {
|
||||
pybind11_fail("The interpreter is already running");
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x030B0000
|
||||
|
||||
Py_InitializeEx(init_signal_handlers ? 1 : 0);
|
||||
|
||||
// Make .py files in the working directory available by default
|
||||
module_::import("sys").attr("path").cast<list>().append(".");
|
||||
// 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.
|
||||
bool special_case = (argv == nullptr || argc <= 0);
|
||||
|
||||
const char *const empty_argv[]{"\0"};
|
||||
const char *const *safe_argv = special_case ? empty_argv : argv;
|
||||
if (special_case) {
|
||||
argc = 1;
|
||||
}
|
||||
|
||||
auto argv_size = static_cast<size_t>(argc);
|
||||
// SetArgv* on python 3 takes wchar_t, so we have to convert.
|
||||
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
|
||||
std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries;
|
||||
widened_argv_entries.reserve(argv_size);
|
||||
for (size_t ii = 0; ii < argv_size; ++ii) {
|
||||
widened_argv_entries.emplace_back(detail::widen_chars(safe_argv[ii]));
|
||||
if (!widened_argv_entries.back()) {
|
||||
// A null here indicates a character-encoding failure or the python
|
||||
// interpreter out of memory. Give up.
|
||||
return;
|
||||
}
|
||||
widened_argv[ii] = widened_argv_entries.back().get();
|
||||
}
|
||||
|
||||
auto *pysys_argv = widened_argv.get();
|
||||
|
||||
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
|
||||
#else
|
||||
PyConfig config;
|
||||
PyConfig_InitIsolatedConfig(&config);
|
||||
config.isolated = 0;
|
||||
config.use_environment = 1;
|
||||
config.install_signal_handlers = init_signal_handlers ? 1 : 0;
|
||||
|
||||
PyStatus status = PyConfig_SetBytesArgv(&config, argc, const_cast<char *const *>(argv));
|
||||
if (PyStatus_Exception(status)) {
|
||||
// A failure here indicates a character-encoding failure or the python
|
||||
// interpreter out of memory. Give up.
|
||||
PyConfig_Clear(&config);
|
||||
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg
|
||||
: "Failed to prepare CPython");
|
||||
}
|
||||
status = Py_InitializeFromConfig(&config);
|
||||
PyConfig_Clear(&config);
|
||||
if (PyStatus_Exception(status)) {
|
||||
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg
|
||||
: "Failed to init CPython");
|
||||
}
|
||||
if (add_program_dir_to_path) {
|
||||
PyRun_SimpleString("import sys, os.path; "
|
||||
"sys.path.insert(0, "
|
||||
"os.path.abspath(os.path.dirname(sys.argv[0])) "
|
||||
"if sys.argv and os.path.exists(sys.argv[0]) else '')");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \rst
|
||||
@ -154,8 +221,13 @@ inline void finalize_interpreter() {
|
||||
// during destruction), so we get the pointer-pointer here and check it after Py_Finalize().
|
||||
detail::internals **internals_ptr_ptr = detail::get_internals_pp();
|
||||
// It could also be stashed in builtins, so look there too:
|
||||
if (builtins.contains(id) && isinstance<capsule>(builtins[id]))
|
||||
if (builtins.contains(id) && isinstance<capsule>(builtins[id])) {
|
||||
internals_ptr_ptr = capsule(builtins[id]);
|
||||
}
|
||||
// Local internals contains data managed by the current interpreter, so we must clear them to
|
||||
// avoid undefined behaviors when initializing another interpreter
|
||||
detail::get_local_internals().registered_types_cpp.clear();
|
||||
detail::get_local_internals().registered_exception_translators.clear();
|
||||
|
||||
Py_Finalize();
|
||||
|
||||
@ -169,6 +241,8 @@ inline void finalize_interpreter() {
|
||||
Scope guard version of `initialize_interpreter` and `finalize_interpreter`.
|
||||
This a move-only guard and only a single instance can exist.
|
||||
|
||||
See `initialize_interpreter` for a discussion of its constructor arguments.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include <pybind11/embed.h>
|
||||
@ -180,8 +254,11 @@ inline void finalize_interpreter() {
|
||||
\endrst */
|
||||
class scoped_interpreter {
|
||||
public:
|
||||
scoped_interpreter(bool init_signal_handlers = true) {
|
||||
initialize_interpreter(init_signal_handlers);
|
||||
explicit scoped_interpreter(bool init_signal_handlers = true,
|
||||
int argc = 0,
|
||||
const char *const *argv = nullptr,
|
||||
bool add_program_dir_to_path = true) {
|
||||
initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path);
|
||||
}
|
||||
|
||||
scoped_interpreter(const scoped_interpreter &) = delete;
|
||||
@ -190,8 +267,9 @@ public:
|
||||
scoped_interpreter &operator=(scoped_interpreter &&) = delete;
|
||||
|
||||
~scoped_interpreter() {
|
||||
if (is_valid)
|
||||
if (is_valid) {
|
||||
finalize_interpreter();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
112
3rdparty/pybind11/include/pybind11/eval.h
vendored
112
3rdparty/pybind11/include/pybind11/eval.h
vendored
@ -1,5 +1,5 @@
|
||||
/*
|
||||
pybind11/exec.h: Support for evaluating Python expressions and statements
|
||||
pybind11/eval.h: Support for evaluating Python expressions and statements
|
||||
from strings and files
|
||||
|
||||
Copyright (c) 2016 Klemens Morgenstern <klemens.morgenstern@ed-chemnitz.de> and
|
||||
@ -13,20 +13,22 @@
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
inline void ensure_builtins_in_globals(object &global) {
|
||||
#if PY_VERSION_HEX < 0x03080000
|
||||
// Running exec and eval on Python 2 and 3 adds `builtins` module under
|
||||
// `__builtins__` key to globals if not yet present.
|
||||
// Python 3.8 made PyRun_String behave similarly. Let's also do that for
|
||||
// older versions, for consistency.
|
||||
if (!global.contains("__builtins__"))
|
||||
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
|
||||
#else
|
||||
(void) global;
|
||||
#endif
|
||||
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000
|
||||
// Running exec and eval adds `builtins` module under `__builtins__` key to
|
||||
// globals if not yet present. Python 3.8 made PyRun_String behave
|
||||
// similarly. Let's also do that for older versions, for consistency. This
|
||||
// was missing from PyPy3.8 7.3.7.
|
||||
if (!global.contains("__builtins__"))
|
||||
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
|
||||
#else
|
||||
(void) global;
|
||||
#endif
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
@ -43,9 +45,10 @@ enum eval_mode {
|
||||
};
|
||||
|
||||
template <eval_mode mode = eval_expr>
|
||||
object eval(str expr, object global = globals(), object local = object()) {
|
||||
if (!local)
|
||||
object eval(const str &expr, object global = globals(), object local = object()) {
|
||||
if (!local) {
|
||||
local = global;
|
||||
}
|
||||
|
||||
detail::ensure_builtins_in_globals(global);
|
||||
|
||||
@ -53,38 +56,45 @@ object eval(str expr, object global = globals(), object local = object()) {
|
||||
this seems to be the only alternative */
|
||||
std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr;
|
||||
|
||||
int start;
|
||||
int start = 0;
|
||||
switch (mode) {
|
||||
case eval_expr: start = Py_eval_input; break;
|
||||
case eval_single_statement: start = Py_single_input; break;
|
||||
case eval_statements: start = Py_file_input; break;
|
||||
default: pybind11_fail("invalid evaluation mode");
|
||||
case eval_expr:
|
||||
start = Py_eval_input;
|
||||
break;
|
||||
case eval_single_statement:
|
||||
start = Py_single_input;
|
||||
break;
|
||||
case eval_statements:
|
||||
start = Py_file_input;
|
||||
break;
|
||||
default:
|
||||
pybind11_fail("invalid evaluation mode");
|
||||
}
|
||||
|
||||
PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
|
||||
if (!result)
|
||||
if (!result) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
|
||||
template <eval_mode mode = eval_expr, size_t N>
|
||||
object eval(const char (&s)[N], object global = globals(), object local = object()) {
|
||||
/* Support raw string literals by removing common leading whitespace */
|
||||
auto expr = (s[0] == '\n') ? str(module_::import("textwrap").attr("dedent")(s))
|
||||
: str(s);
|
||||
return eval<mode>(expr, global, local);
|
||||
auto expr = (s[0] == '\n') ? str(module_::import("textwrap").attr("dedent")(s)) : str(s);
|
||||
return eval<mode>(expr, std::move(global), std::move(local));
|
||||
}
|
||||
|
||||
inline void exec(str expr, object global = globals(), object local = object()) {
|
||||
eval<eval_statements>(expr, global, local);
|
||||
inline void exec(const str &expr, object global = globals(), object local = object()) {
|
||||
eval<eval_statements>(expr, std::move(global), std::move(local));
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
void exec(const char (&s)[N], object global = globals(), object local = object()) {
|
||||
eval<eval_statements>(s, global, local);
|
||||
eval<eval_statements>(s, std::move(global), std::move(local));
|
||||
}
|
||||
|
||||
#if defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03000000
|
||||
#if defined(PYPY_VERSION)
|
||||
template <eval_mode mode = eval_statements>
|
||||
object eval_file(str, object, object) {
|
||||
pybind11_fail("eval_file not supported in PyPy3. Use eval");
|
||||
@ -100,51 +110,45 @@ object eval_file(str) {
|
||||
#else
|
||||
template <eval_mode mode = eval_statements>
|
||||
object eval_file(str fname, object global = globals(), object local = object()) {
|
||||
if (!local)
|
||||
if (!local) {
|
||||
local = global;
|
||||
}
|
||||
|
||||
detail::ensure_builtins_in_globals(global);
|
||||
|
||||
int start;
|
||||
int start = 0;
|
||||
switch (mode) {
|
||||
case eval_expr: start = Py_eval_input; break;
|
||||
case eval_single_statement: start = Py_single_input; break;
|
||||
case eval_statements: start = Py_file_input; break;
|
||||
default: pybind11_fail("invalid evaluation mode");
|
||||
case eval_expr:
|
||||
start = Py_eval_input;
|
||||
break;
|
||||
case eval_single_statement:
|
||||
start = Py_single_input;
|
||||
break;
|
||||
case eval_statements:
|
||||
start = Py_file_input;
|
||||
break;
|
||||
default:
|
||||
pybind11_fail("invalid evaluation mode");
|
||||
}
|
||||
|
||||
int closeFile = 1;
|
||||
std::string fname_str = (std::string) fname;
|
||||
#if PY_VERSION_HEX >= 0x03040000
|
||||
FILE *f = _Py_fopen_obj(fname.ptr(), "r");
|
||||
#elif PY_VERSION_HEX >= 0x03000000
|
||||
FILE *f = _Py_fopen(fname.ptr(), "r");
|
||||
#else
|
||||
/* No unicode support in open() :( */
|
||||
auto fobj = reinterpret_steal<object>(PyFile_FromString(
|
||||
const_cast<char *>(fname_str.c_str()),
|
||||
const_cast<char*>("r")));
|
||||
FILE *f = nullptr;
|
||||
if (fobj)
|
||||
f = PyFile_AsFile(fobj.ptr());
|
||||
closeFile = 0;
|
||||
#endif
|
||||
if (!f) {
|
||||
PyErr_Clear();
|
||||
pybind11_fail("File \"" + fname_str + "\" could not be opened!");
|
||||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION)
|
||||
PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(),
|
||||
local.ptr());
|
||||
(void) closeFile;
|
||||
#else
|
||||
PyObject *result = PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(),
|
||||
local.ptr(), closeFile);
|
||||
#endif
|
||||
if (!global.contains("__file__")) {
|
||||
global["__file__"] = std::move(fname);
|
||||
}
|
||||
|
||||
if (!result)
|
||||
PyObject *result
|
||||
= PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), local.ptr(), closeFile);
|
||||
|
||||
if (!result) {
|
||||
throw error_already_set();
|
||||
}
|
||||
return reinterpret_steal<object>(result);
|
||||
}
|
||||
#endif
|
||||
|
70
3rdparty/pybind11/include/pybind11/functional.h
vendored
70
3rdparty/pybind11/include/pybind11/functional.h
vendored
@ -10,6 +10,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
@ -19,18 +20,21 @@ template <typename Return, typename... Args>
|
||||
struct type_caster<std::function<Return(Args...)>> {
|
||||
using type = std::function<Return(Args...)>;
|
||||
using retval_type = conditional_t<std::is_same<Return, void>::value, void_type, Return>;
|
||||
using function_type = Return (*) (Args...);
|
||||
using function_type = Return (*)(Args...);
|
||||
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (src.is_none()) {
|
||||
// Defer accepting None to other overloads (if we aren't in convert mode):
|
||||
if (!convert) return false;
|
||||
if (!convert) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!isinstance<function>(src))
|
||||
if (!isinstance<function>(src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto func = reinterpret_borrow<function>(src);
|
||||
|
||||
@ -43,24 +47,44 @@ public:
|
||||
captured variables), in which case the roundtrip can be avoided.
|
||||
*/
|
||||
if (auto cfunc = func.cpp_function()) {
|
||||
auto c = reinterpret_borrow<capsule>(PyCFunction_GET_SELF(cfunc.ptr()));
|
||||
auto rec = (function_record *) c;
|
||||
auto *cfunc_self = PyCFunction_GET_SELF(cfunc.ptr());
|
||||
if (isinstance<capsule>(cfunc_self)) {
|
||||
auto c = reinterpret_borrow<capsule>(cfunc_self);
|
||||
auto *rec = (function_record *) c;
|
||||
|
||||
if (rec && rec->is_stateless &&
|
||||
same_type(typeid(function_type), *reinterpret_cast<const std::type_info *>(rec->data[1]))) {
|
||||
struct capture { function_type f; };
|
||||
value = ((capture *) &rec->data)->f;
|
||||
return true;
|
||||
while (rec != nullptr) {
|
||||
if (rec->is_stateless
|
||||
&& same_type(typeid(function_type),
|
||||
*reinterpret_cast<const std::type_info *>(rec->data[1]))) {
|
||||
struct capture {
|
||||
function_type f;
|
||||
};
|
||||
value = ((capture *) &rec->data)->f;
|
||||
return true;
|
||||
}
|
||||
rec = rec->next;
|
||||
}
|
||||
}
|
||||
// PYPY segfaults here when passing builtin function like sum.
|
||||
// Raising an fail exception here works to prevent the segfault, but only on gcc.
|
||||
// See PR #1413 for full details
|
||||
}
|
||||
|
||||
// ensure GIL is held during functor destruction
|
||||
struct func_handle {
|
||||
function f;
|
||||
func_handle(function&& f_) : f(std::move(f_)) {}
|
||||
func_handle(const func_handle& f_) {
|
||||
#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
|
||||
// This triggers a syntax error under very special conditions (very weird indeed).
|
||||
explicit
|
||||
#endif
|
||||
func_handle(function &&f_) noexcept
|
||||
: f(std::move(f_)) {
|
||||
}
|
||||
func_handle(const func_handle &f_) { operator=(f_); }
|
||||
func_handle &operator=(const func_handle &f_) {
|
||||
gil_scoped_acquire acq;
|
||||
f = f_.f;
|
||||
return *this;
|
||||
}
|
||||
~func_handle() {
|
||||
gil_scoped_acquire acq;
|
||||
@ -71,12 +95,11 @@ public:
|
||||
// to emulate 'move initialization capture' in C++11
|
||||
struct func_wrapper {
|
||||
func_handle hfunc;
|
||||
func_wrapper(func_handle&& hf): hfunc(std::move(hf)) {}
|
||||
explicit func_wrapper(func_handle &&hf) noexcept : hfunc(std::move(hf)) {}
|
||||
Return operator()(Args... args) const {
|
||||
gil_scoped_acquire acq;
|
||||
object retval(hfunc.f(std::forward<Args>(args)...));
|
||||
/* Visual studio 2015 parser issue: need parentheses around this expression */
|
||||
return (retval.template cast<Return>());
|
||||
// casts the returned object as a rvalue to the return type
|
||||
return hfunc.f(std::forward<Args>(args)...).template cast<Return>();
|
||||
}
|
||||
};
|
||||
|
||||
@ -86,18 +109,21 @@ public:
|
||||
|
||||
template <typename Func>
|
||||
static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
|
||||
if (!f_)
|
||||
if (!f_) {
|
||||
return none().inc_ref();
|
||||
}
|
||||
|
||||
auto result = f_.template target<function_type>();
|
||||
if (result)
|
||||
if (result) {
|
||||
return cpp_function(*result, policy).release();
|
||||
else
|
||||
return cpp_function(std::forward<Func>(f_), policy).release();
|
||||
}
|
||||
return cpp_function(std::forward<Func>(f_), policy).release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(type, _("Callable[[") + concat(make_caster<Args>::name...) + _("], ")
|
||||
+ make_caster<retval_type>::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(type,
|
||||
const_name("Callable[[") + concat(make_caster<Args>::name...)
|
||||
+ const_name("], ") + make_caster<retval_type>::name
|
||||
+ const_name("]"));
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
202
3rdparty/pybind11/include/pybind11/gil.h
vendored
Normal file
202
3rdparty/pybind11/include/pybind11/gil.h
vendored
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
pybind11/gil.h: RAII helpers for managing the GIL
|
||||
|
||||
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
|
||||
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "detail/common.h"
|
||||
#include "detail/internals.h"
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
// forward declarations
|
||||
PyThreadState *get_thread_state_unchecked();
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
#if defined(WITH_THREAD) && !defined(PYPY_VERSION)
|
||||
|
||||
/* The functions below essentially reproduce the PyGILState_* API using a RAII
|
||||
* pattern, but there are a few important differences:
|
||||
*
|
||||
* 1. When acquiring the GIL from an non-main thread during the finalization
|
||||
* phase, the GILState API blindly terminates the calling thread, which
|
||||
* is often not what is wanted. This API does not do this.
|
||||
*
|
||||
* 2. The gil_scoped_release function can optionally cut the relationship
|
||||
* of a PyThreadState and its associated thread, which allows moving it to
|
||||
* another thread (this is a fairly rare/advanced use case).
|
||||
*
|
||||
* 3. The reference count of an acquired thread state can be controlled. This
|
||||
* can be handy to prevent cases where callbacks issued from an external
|
||||
* thread would otherwise constantly construct and destroy thread state data
|
||||
* structures.
|
||||
*
|
||||
* See the Python bindings of NanoGUI (http://github.com/wjakob/nanogui) for an
|
||||
* example which uses features 2 and 3 to migrate the Python thread of
|
||||
* execution to another thread (to run the event loop on the original thread,
|
||||
* in this case).
|
||||
*/
|
||||
|
||||
class gil_scoped_acquire {
|
||||
public:
|
||||
PYBIND11_NOINLINE gil_scoped_acquire() {
|
||||
auto &internals = detail::get_internals();
|
||||
tstate = (PyThreadState *) PYBIND11_TLS_GET_VALUE(internals.tstate);
|
||||
|
||||
if (!tstate) {
|
||||
/* Check if the GIL was acquired using the PyGILState_* API instead (e.g. if
|
||||
calling from a Python thread). Since we use a different key, this ensures
|
||||
we don't create a new thread state and deadlock in PyEval_AcquireThread
|
||||
below. Note we don't save this state with internals.tstate, since we don't
|
||||
create it we would fail to clear it (its reference count should be > 0). */
|
||||
tstate = PyGILState_GetThisThreadState();
|
||||
}
|
||||
|
||||
if (!tstate) {
|
||||
tstate = PyThreadState_New(internals.istate);
|
||||
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||
if (!tstate) {
|
||||
pybind11_fail("scoped_acquire: could not create thread state!");
|
||||
}
|
||||
# endif
|
||||
tstate->gilstate_counter = 0;
|
||||
PYBIND11_TLS_REPLACE_VALUE(internals.tstate, tstate);
|
||||
} else {
|
||||
release = detail::get_thread_state_unchecked() != tstate;
|
||||
}
|
||||
|
||||
if (release) {
|
||||
PyEval_AcquireThread(tstate);
|
||||
}
|
||||
|
||||
inc_ref();
|
||||
}
|
||||
|
||||
void inc_ref() { ++tstate->gilstate_counter; }
|
||||
|
||||
PYBIND11_NOINLINE void dec_ref() {
|
||||
--tstate->gilstate_counter;
|
||||
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||
if (detail::get_thread_state_unchecked() != tstate) {
|
||||
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
|
||||
}
|
||||
if (tstate->gilstate_counter < 0) {
|
||||
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
|
||||
}
|
||||
# endif
|
||||
if (tstate->gilstate_counter == 0) {
|
||||
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||
if (!release) {
|
||||
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
|
||||
}
|
||||
# endif
|
||||
PyThreadState_Clear(tstate);
|
||||
if (active) {
|
||||
PyThreadState_DeleteCurrent();
|
||||
}
|
||||
PYBIND11_TLS_DELETE_VALUE(detail::get_internals().tstate);
|
||||
release = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// This method will disable the PyThreadState_DeleteCurrent call and the
|
||||
/// GIL won't be acquired. This method should be used if the interpreter
|
||||
/// could be shutting down when this is called, as thread deletion is not
|
||||
/// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
|
||||
/// protect subsequent code.
|
||||
PYBIND11_NOINLINE void disarm() { active = false; }
|
||||
|
||||
PYBIND11_NOINLINE ~gil_scoped_acquire() {
|
||||
dec_ref();
|
||||
if (release) {
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PyThreadState *tstate = nullptr;
|
||||
bool release = true;
|
||||
bool active = true;
|
||||
};
|
||||
|
||||
class gil_scoped_release {
|
||||
public:
|
||||
explicit gil_scoped_release(bool disassoc = false) : disassoc(disassoc) {
|
||||
// `get_internals()` must be called here unconditionally in order to initialize
|
||||
// `internals.tstate` for subsequent `gil_scoped_acquire` calls. Otherwise, an
|
||||
// initialization race could occur as multiple threads try `gil_scoped_acquire`.
|
||||
auto &internals = detail::get_internals();
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-prefer-member-initializer)
|
||||
tstate = PyEval_SaveThread();
|
||||
if (disassoc) {
|
||||
// Python >= 3.7 can remove this, it's an int before 3.7
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
auto key = internals.tstate;
|
||||
PYBIND11_TLS_DELETE_VALUE(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// This method will disable the PyThreadState_DeleteCurrent call and the
|
||||
/// GIL won't be acquired. This method should be used if the interpreter
|
||||
/// could be shutting down when this is called, as thread deletion is not
|
||||
/// allowed during shutdown. Check _Py_IsFinalizing() on Python 3.7+, and
|
||||
/// protect subsequent code.
|
||||
PYBIND11_NOINLINE void disarm() { active = false; }
|
||||
|
||||
~gil_scoped_release() {
|
||||
if (!tstate) {
|
||||
return;
|
||||
}
|
||||
// `PyEval_RestoreThread()` should not be called if runtime is finalizing
|
||||
if (active) {
|
||||
PyEval_RestoreThread(tstate);
|
||||
}
|
||||
if (disassoc) {
|
||||
// Python >= 3.7 can remove this, it's an int before 3.7
|
||||
// NOLINTNEXTLINE(readability-qualified-auto)
|
||||
auto key = detail::get_internals().tstate;
|
||||
PYBIND11_TLS_REPLACE_VALUE(key, tstate);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
PyThreadState *tstate;
|
||||
bool disassoc;
|
||||
bool active = true;
|
||||
};
|
||||
#elif defined(PYPY_VERSION)
|
||||
class gil_scoped_acquire {
|
||||
PyGILState_STATE state;
|
||||
|
||||
public:
|
||||
gil_scoped_acquire() { state = PyGILState_Ensure(); }
|
||||
~gil_scoped_acquire() { PyGILState_Release(state); }
|
||||
void disarm() {}
|
||||
};
|
||||
|
||||
class gil_scoped_release {
|
||||
PyThreadState *state;
|
||||
|
||||
public:
|
||||
gil_scoped_release() { state = PyEval_SaveThread(); }
|
||||
~gil_scoped_release() { PyEval_RestoreThread(state); }
|
||||
void disarm() {}
|
||||
};
|
||||
#else
|
||||
class gil_scoped_acquire {
|
||||
void disarm() {}
|
||||
};
|
||||
class gil_scoped_release {
|
||||
void disarm() {}
|
||||
};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
145
3rdparty/pybind11/include/pybind11/iostream.h
vendored
145
3rdparty/pybind11/include/pybind11/iostream.h
vendored
@ -5,17 +5,31 @@
|
||||
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
WARNING: The implementation in this file is NOT thread safe. Multiple
|
||||
threads writing to a redirected ostream concurrently cause data races
|
||||
and potentially buffer overflows. Therefore it is currently a requirement
|
||||
that all (possibly) concurrent redirected ostream writes are protected by
|
||||
a mutex.
|
||||
#HelpAppreciated: Work on iostream.h thread safety.
|
||||
For more background see the discussions under
|
||||
https://github.com/pybind/pybind11/pull/2982 and
|
||||
https://github.com/pybind/pybind11/pull/2995.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#include <streambuf>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <streambuf>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
@ -38,50 +52,85 @@ private:
|
||||
return sync() == 0 ? traits_type::not_eof(c) : traits_type::eof();
|
||||
}
|
||||
|
||||
// This function must be non-virtual to be called in a destructor. If the
|
||||
// rare MSVC test failure shows up with this version, then this should be
|
||||
// simplified to a fully qualified call.
|
||||
int _sync() {
|
||||
if (pbase() != pptr()) {
|
||||
// This subtraction cannot be negative, so dropping the sign
|
||||
str line(pbase(), static_cast<size_t>(pptr() - pbase()));
|
||||
// Computes how many bytes at the end of the buffer are part of an
|
||||
// incomplete sequence of UTF-8 bytes.
|
||||
// Precondition: pbase() < pptr()
|
||||
size_t utf8_remainder() const {
|
||||
const auto rbase = std::reverse_iterator<char *>(pbase());
|
||||
const auto rpptr = std::reverse_iterator<char *>(pptr());
|
||||
auto is_ascii = [](char c) { return (static_cast<unsigned char>(c) & 0x80) == 0x00; };
|
||||
auto is_leading = [](char c) { return (static_cast<unsigned char>(c) & 0xC0) == 0xC0; };
|
||||
auto is_leading_2b = [](char c) { return static_cast<unsigned char>(c) <= 0xDF; };
|
||||
auto is_leading_3b = [](char c) { return static_cast<unsigned char>(c) <= 0xEF; };
|
||||
// If the last character is ASCII, there are no incomplete code points
|
||||
if (is_ascii(*rpptr)) {
|
||||
return 0;
|
||||
}
|
||||
// Otherwise, work back from the end of the buffer and find the first
|
||||
// UTF-8 leading byte
|
||||
const auto rpend = rbase - rpptr >= 3 ? rpptr + 3 : rbase;
|
||||
const auto leading = std::find_if(rpptr, rpend, is_leading);
|
||||
if (leading == rbase) {
|
||||
return 0;
|
||||
}
|
||||
const auto dist = static_cast<size_t>(leading - rpptr);
|
||||
size_t remainder = 0;
|
||||
|
||||
{
|
||||
gil_scoped_acquire tmp;
|
||||
pywrite(line);
|
||||
if (dist == 0) {
|
||||
remainder = 1; // 1-byte code point is impossible
|
||||
} else if (dist == 1) {
|
||||
remainder = is_leading_2b(*leading) ? 0 : dist + 1;
|
||||
} else if (dist == 2) {
|
||||
remainder = is_leading_3b(*leading) ? 0 : dist + 1;
|
||||
}
|
||||
// else if (dist >= 3), at least 4 bytes before encountering an UTF-8
|
||||
// leading byte, either no remainder or invalid UTF-8.
|
||||
// Invalid UTF-8 will cause an exception later when converting
|
||||
// to a Python string, so that's not handled here.
|
||||
return remainder;
|
||||
}
|
||||
|
||||
// This function must be non-virtual to be called in a destructor.
|
||||
int _sync() {
|
||||
if (pbase() != pptr()) { // If buffer is not empty
|
||||
gil_scoped_acquire tmp;
|
||||
// This subtraction cannot be negative, so dropping the sign.
|
||||
auto size = static_cast<size_t>(pptr() - pbase());
|
||||
size_t remainder = utf8_remainder();
|
||||
|
||||
if (size > remainder) {
|
||||
str line(pbase(), size - remainder);
|
||||
pywrite(std::move(line));
|
||||
pyflush();
|
||||
}
|
||||
|
||||
// Copy the remainder at the end of the buffer to the beginning:
|
||||
if (remainder > 0) {
|
||||
std::memmove(pbase(), pptr() - remainder, remainder);
|
||||
}
|
||||
setp(pbase(), epptr());
|
||||
pbump(static_cast<int>(remainder));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sync() override {
|
||||
return _sync();
|
||||
}
|
||||
int sync() override { return _sync(); }
|
||||
|
||||
public:
|
||||
|
||||
pythonbuf(object pyostream, size_t buffer_size = 1024)
|
||||
: buf_size(buffer_size),
|
||||
d_buffer(new char[buf_size]),
|
||||
pywrite(pyostream.attr("write")),
|
||||
explicit pythonbuf(const object &pyostream, size_t buffer_size = 1024)
|
||||
: buf_size(buffer_size), d_buffer(new char[buf_size]), pywrite(pyostream.attr("write")),
|
||||
pyflush(pyostream.attr("flush")) {
|
||||
setp(d_buffer.get(), d_buffer.get() + buf_size - 1);
|
||||
}
|
||||
|
||||
pythonbuf(pythonbuf&&) = default;
|
||||
pythonbuf(pythonbuf &&) = default;
|
||||
|
||||
/// Sync before destroy
|
||||
~pythonbuf() override {
|
||||
_sync();
|
||||
}
|
||||
~pythonbuf() override { _sync(); }
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
|
||||
/** \rst
|
||||
This a move-only guard that redirects output.
|
||||
|
||||
@ -102,8 +151,9 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
.. code-block:: cpp
|
||||
|
||||
{
|
||||
py::scoped_ostream_redirect output{std::cerr, py::module_::import("sys").attr("stderr")};
|
||||
std::cerr << "Hello, World!";
|
||||
py::scoped_ostream_redirect output{
|
||||
std::cerr, py::module::import("sys").attr("stderr")};
|
||||
std::cout << "Hello, World!";
|
||||
}
|
||||
\endrst */
|
||||
class scoped_ostream_redirect {
|
||||
@ -113,16 +163,14 @@ protected:
|
||||
detail::pythonbuf buffer;
|
||||
|
||||
public:
|
||||
scoped_ostream_redirect(
|
||||
std::ostream &costream = std::cout,
|
||||
object pyostream = module_::import("sys").attr("stdout"))
|
||||
explicit scoped_ostream_redirect(std::ostream &costream = std::cout,
|
||||
const object &pyostream
|
||||
= module_::import("sys").attr("stdout"))
|
||||
: costream(costream), buffer(pyostream) {
|
||||
old = costream.rdbuf(&buffer);
|
||||
}
|
||||
|
||||
~scoped_ostream_redirect() {
|
||||
costream.rdbuf(old);
|
||||
}
|
||||
~scoped_ostream_redirect() { costream.rdbuf(old); }
|
||||
|
||||
scoped_ostream_redirect(const scoped_ostream_redirect &) = delete;
|
||||
scoped_ostream_redirect(scoped_ostream_redirect &&other) = default;
|
||||
@ -130,7 +178,6 @@ public:
|
||||
scoped_ostream_redirect &operator=(scoped_ostream_redirect &&) = delete;
|
||||
};
|
||||
|
||||
|
||||
/** \rst
|
||||
Like `scoped_ostream_redirect`, but redirects cerr by default. This class
|
||||
is provided primary to make ``py::call_guard`` easier to make.
|
||||
@ -144,13 +191,12 @@ public:
|
||||
\endrst */
|
||||
class scoped_estream_redirect : public scoped_ostream_redirect {
|
||||
public:
|
||||
scoped_estream_redirect(
|
||||
std::ostream &costream = std::cerr,
|
||||
object pyostream = module_::import("sys").attr("stderr"))
|
||||
: scoped_ostream_redirect(costream,pyostream) {}
|
||||
explicit scoped_estream_redirect(std::ostream &costream = std::cerr,
|
||||
const object &pyostream
|
||||
= module_::import("sys").attr("stderr"))
|
||||
: scoped_ostream_redirect(costream, pyostream) {}
|
||||
};
|
||||
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
// Class to redirect output as a context manager. C++ backend.
|
||||
@ -161,14 +207,16 @@ class OstreamRedirect {
|
||||
std::unique_ptr<scoped_estream_redirect> redirect_stderr;
|
||||
|
||||
public:
|
||||
OstreamRedirect(bool do_stdout = true, bool do_stderr = true)
|
||||
explicit OstreamRedirect(bool do_stdout = true, bool do_stderr = true)
|
||||
: do_stdout_(do_stdout), do_stderr_(do_stderr) {}
|
||||
|
||||
void enter() {
|
||||
if (do_stdout_)
|
||||
if (do_stdout_) {
|
||||
redirect_stdout.reset(new scoped_ostream_redirect());
|
||||
if (do_stderr_)
|
||||
}
|
||||
if (do_stderr_) {
|
||||
redirect_stderr.reset(new scoped_estream_redirect());
|
||||
}
|
||||
}
|
||||
|
||||
void exit() {
|
||||
@ -206,11 +254,12 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
m.noisy_function_with_error_printing()
|
||||
|
||||
\endrst */
|
||||
inline class_<detail::OstreamRedirect> add_ostream_redirect(module_ m, std::string name = "ostream_redirect") {
|
||||
return class_<detail::OstreamRedirect>(m, name.c_str(), module_local())
|
||||
.def(init<bool,bool>(), arg("stdout")=true, arg("stderr")=true)
|
||||
inline class_<detail::OstreamRedirect>
|
||||
add_ostream_redirect(module_ m, const std::string &name = "ostream_redirect") {
|
||||
return class_<detail::OstreamRedirect>(std::move(m), name.c_str(), module_local())
|
||||
.def(init<bool, bool>(), arg("stdout") = true, arg("stderr") = true)
|
||||
.def("__enter__", &detail::OstreamRedirect::enter)
|
||||
.def("__exit__", [](detail::OstreamRedirect &self_, args) { self_.exit(); });
|
||||
.def("__exit__", [](detail::OstreamRedirect &self_, const args &) { self_.exit(); });
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
1404
3rdparty/pybind11/include/pybind11/numpy.h
vendored
1404
3rdparty/pybind11/include/pybind11/numpy.h
vendored
File diff suppressed because it is too large
Load Diff
240
3rdparty/pybind11/include/pybind11/operators.h
vendored
240
3rdparty/pybind11/include/pybind11/operators.h
vendored
@ -11,24 +11,55 @@
|
||||
|
||||
#include "pybind11.h"
|
||||
|
||||
#if defined(__clang__) && !defined(__INTEL_COMPILER)
|
||||
# pragma clang diagnostic ignored "-Wunsequenced" // multiple unsequenced modifications to 'self' (when using def(py::self OP Type()))
|
||||
#elif defined(_MSC_VER)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
/// Enumeration with all supported operator types
|
||||
enum op_id : int {
|
||||
op_add, op_sub, op_mul, op_div, op_mod, op_divmod, op_pow, op_lshift,
|
||||
op_rshift, op_and, op_xor, op_or, op_neg, op_pos, op_abs, op_invert,
|
||||
op_int, op_long, op_float, op_str, op_cmp, op_gt, op_ge, op_lt, op_le,
|
||||
op_eq, op_ne, op_iadd, op_isub, op_imul, op_idiv, op_imod, op_ilshift,
|
||||
op_irshift, op_iand, op_ixor, op_ior, op_complex, op_bool, op_nonzero,
|
||||
op_repr, op_truediv, op_itruediv, op_hash
|
||||
op_add,
|
||||
op_sub,
|
||||
op_mul,
|
||||
op_div,
|
||||
op_mod,
|
||||
op_divmod,
|
||||
op_pow,
|
||||
op_lshift,
|
||||
op_rshift,
|
||||
op_and,
|
||||
op_xor,
|
||||
op_or,
|
||||
op_neg,
|
||||
op_pos,
|
||||
op_abs,
|
||||
op_invert,
|
||||
op_int,
|
||||
op_long,
|
||||
op_float,
|
||||
op_str,
|
||||
op_cmp,
|
||||
op_gt,
|
||||
op_ge,
|
||||
op_lt,
|
||||
op_le,
|
||||
op_eq,
|
||||
op_ne,
|
||||
op_iadd,
|
||||
op_isub,
|
||||
op_imul,
|
||||
op_idiv,
|
||||
op_imod,
|
||||
op_ilshift,
|
||||
op_irshift,
|
||||
op_iand,
|
||||
op_ixor,
|
||||
op_ior,
|
||||
op_complex,
|
||||
op_bool,
|
||||
op_nonzero,
|
||||
op_repr,
|
||||
op_truediv,
|
||||
op_itruediv,
|
||||
op_hash
|
||||
};
|
||||
|
||||
enum op_type : int {
|
||||
@ -37,125 +68,126 @@ enum op_type : int {
|
||||
op_u /* unary operator */
|
||||
};
|
||||
|
||||
struct self_t { };
|
||||
struct self_t {};
|
||||
static const self_t self = self_t();
|
||||
|
||||
/// Type for an unused type slot
|
||||
struct undefined_t { };
|
||||
struct undefined_t {};
|
||||
|
||||
/// Don't warn about an unused variable
|
||||
inline self_t __self() { return self; }
|
||||
|
||||
/// base template of operator implementations
|
||||
template <op_id, op_type, typename B, typename L, typename R> struct op_impl { };
|
||||
template <op_id, op_type, typename B, typename L, typename R>
|
||||
struct op_impl {};
|
||||
|
||||
/// Operator implementation generator
|
||||
template <op_id id, op_type ot, typename L, typename R> struct op_ {
|
||||
template <typename Class, typename... Extra> void execute(Class &cl, const Extra&... extra) const {
|
||||
template <op_id id, op_type ot, typename L, typename R>
|
||||
struct op_ {
|
||||
template <typename Class, typename... Extra>
|
||||
void execute(Class &cl, const Extra &...extra) const {
|
||||
using Base = typename Class::type;
|
||||
using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>;
|
||||
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
|
||||
using op = op_impl<id, ot, Base, L_type, R_type>;
|
||||
cl.def(op::name(), &op::execute, is_operator(), extra...);
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (id == op_truediv || id == op_itruediv)
|
||||
cl.def(id == op_itruediv ? "__idiv__" : ot == op_l ? "__div__" : "__rdiv__",
|
||||
&op::execute, is_operator(), extra...);
|
||||
#endif
|
||||
}
|
||||
template <typename Class, typename... Extra> void execute_cast(Class &cl, const Extra&... extra) const {
|
||||
template <typename Class, typename... Extra>
|
||||
void execute_cast(Class &cl, const Extra &...extra) const {
|
||||
using Base = typename Class::type;
|
||||
using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>;
|
||||
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
|
||||
using op = op_impl<id, ot, Base, L_type, R_type>;
|
||||
cl.def(op::name(), &op::execute_cast, is_operator(), extra...);
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
if (id == op_truediv || id == op_itruediv)
|
||||
cl.def(id == op_itruediv ? "__idiv__" : ot == op_l ? "__div__" : "__rdiv__",
|
||||
&op::execute, is_operator(), extra...);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \
|
||||
template <typename B, typename L, typename R> struct op_impl<op_##id, op_l, B, L, R> { \
|
||||
static char const* name() { return "__" #id "__"; } \
|
||||
static auto execute(const L &l, const R &r) -> decltype(expr) { return (expr); } \
|
||||
static B execute_cast(const L &l, const R &r) { return B(expr); } \
|
||||
}; \
|
||||
template <typename B, typename L, typename R> struct op_impl<op_##id, op_r, B, L, R> { \
|
||||
static char const* name() { return "__" #rid "__"; } \
|
||||
static auto execute(const R &r, const L &l) -> decltype(expr) { return (expr); } \
|
||||
static B execute_cast(const R &r, const L &l) { return B(expr); } \
|
||||
}; \
|
||||
inline op_<op_##id, op_l, self_t, self_t> op(const self_t &, const self_t &) { \
|
||||
return op_<op_##id, op_l, self_t, self_t>(); \
|
||||
} \
|
||||
template <typename T> op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \
|
||||
return op_<op_##id, op_l, self_t, T>(); \
|
||||
} \
|
||||
template <typename T> op_<op_##id, op_r, T, self_t> op(const T &, const self_t &) { \
|
||||
return op_<op_##id, op_r, T, self_t>(); \
|
||||
}
|
||||
#define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \
|
||||
template <typename B, typename L, typename R> \
|
||||
struct op_impl<op_##id, op_l, B, L, R> { \
|
||||
static char const *name() { return "__" #id "__"; } \
|
||||
static auto execute(const L &l, const R &r) -> decltype(expr) { return (expr); } \
|
||||
static B execute_cast(const L &l, const R &r) { return B(expr); } \
|
||||
}; \
|
||||
template <typename B, typename L, typename R> \
|
||||
struct op_impl<op_##id, op_r, B, L, R> { \
|
||||
static char const *name() { return "__" #rid "__"; } \
|
||||
static auto execute(const R &r, const L &l) -> decltype(expr) { return (expr); } \
|
||||
static B execute_cast(const R &r, const L &l) { return B(expr); } \
|
||||
}; \
|
||||
inline op_<op_##id, op_l, self_t, self_t> op(const self_t &, const self_t &) { \
|
||||
return op_<op_##id, op_l, self_t, self_t>(); \
|
||||
} \
|
||||
template <typename T> \
|
||||
op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \
|
||||
return op_<op_##id, op_l, self_t, T>(); \
|
||||
} \
|
||||
template <typename T> \
|
||||
op_<op_##id, op_r, T, self_t> op(const T &, const self_t &) { \
|
||||
return op_<op_##id, op_r, T, self_t>(); \
|
||||
}
|
||||
|
||||
#define PYBIND11_INPLACE_OPERATOR(id, op, expr) \
|
||||
template <typename B, typename L, typename R> struct op_impl<op_##id, op_l, B, L, R> { \
|
||||
static char const* name() { return "__" #id "__"; } \
|
||||
static auto execute(L &l, const R &r) -> decltype(expr) { return expr; } \
|
||||
static B execute_cast(L &l, const R &r) { return B(expr); } \
|
||||
}; \
|
||||
template <typename T> op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \
|
||||
return op_<op_##id, op_l, self_t, T>(); \
|
||||
}
|
||||
#define PYBIND11_INPLACE_OPERATOR(id, op, expr) \
|
||||
template <typename B, typename L, typename R> \
|
||||
struct op_impl<op_##id, op_l, B, L, R> { \
|
||||
static char const *name() { return "__" #id "__"; } \
|
||||
static auto execute(L &l, const R &r) -> decltype(expr) { return expr; } \
|
||||
static B execute_cast(L &l, const R &r) { return B(expr); } \
|
||||
}; \
|
||||
template <typename T> \
|
||||
op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \
|
||||
return op_<op_##id, op_l, self_t, T>(); \
|
||||
}
|
||||
|
||||
#define PYBIND11_UNARY_OPERATOR(id, op, expr) \
|
||||
template <typename B, typename L> struct op_impl<op_##id, op_u, B, L, undefined_t> { \
|
||||
static char const* name() { return "__" #id "__"; } \
|
||||
static auto execute(const L &l) -> decltype(expr) { return expr; } \
|
||||
static B execute_cast(const L &l) { return B(expr); } \
|
||||
}; \
|
||||
inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) { \
|
||||
return op_<op_##id, op_u, self_t, undefined_t>(); \
|
||||
}
|
||||
#define PYBIND11_UNARY_OPERATOR(id, op, expr) \
|
||||
template <typename B, typename L> \
|
||||
struct op_impl<op_##id, op_u, B, L, undefined_t> { \
|
||||
static char const *name() { return "__" #id "__"; } \
|
||||
static auto execute(const L &l) -> decltype(expr) { return expr; } \
|
||||
static B execute_cast(const L &l) { return B(expr); } \
|
||||
}; \
|
||||
inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) { \
|
||||
return op_<op_##id, op_u, self_t, undefined_t>(); \
|
||||
}
|
||||
|
||||
PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r)
|
||||
PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r)
|
||||
PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l * r)
|
||||
PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r)
|
||||
PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r)
|
||||
PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r)
|
||||
PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r)
|
||||
PYBIND11_BINARY_OPERATOR(and, rand, operator&, l & r)
|
||||
PYBIND11_BINARY_OPERATOR(xor, rxor, operator^, l ^ r)
|
||||
PYBIND11_BINARY_OPERATOR(eq, eq, operator==, l == r)
|
||||
PYBIND11_BINARY_OPERATOR(ne, ne, operator!=, l != r)
|
||||
PYBIND11_BINARY_OPERATOR(or, ror, operator|, l | r)
|
||||
PYBIND11_BINARY_OPERATOR(gt, lt, operator>, l > r)
|
||||
PYBIND11_BINARY_OPERATOR(ge, le, operator>=, l >= r)
|
||||
PYBIND11_BINARY_OPERATOR(lt, gt, operator<, l < r)
|
||||
PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r)
|
||||
//PYBIND11_BINARY_OPERATOR(pow, rpow, pow, std::pow(l, r))
|
||||
PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r)
|
||||
PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r)
|
||||
PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r)
|
||||
PYBIND11_INPLACE_OPERATOR(itruediv, operator/=, l /= r)
|
||||
PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r)
|
||||
PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r)
|
||||
PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r)
|
||||
PYBIND11_INPLACE_OPERATOR(iand, operator&=, l &= r)
|
||||
PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r)
|
||||
PYBIND11_INPLACE_OPERATOR(ior, operator|=, l |= r)
|
||||
PYBIND11_UNARY_OPERATOR(neg, operator-, -l)
|
||||
PYBIND11_UNARY_OPERATOR(pos, operator+, +l)
|
||||
PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r)
|
||||
PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r)
|
||||
PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l *r)
|
||||
PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r)
|
||||
PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r)
|
||||
PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r)
|
||||
PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r)
|
||||
PYBIND11_BINARY_OPERATOR(and, rand, operator&, l &r)
|
||||
PYBIND11_BINARY_OPERATOR(xor, rxor, operator^, l ^ r)
|
||||
PYBIND11_BINARY_OPERATOR(eq, eq, operator==, l == r)
|
||||
PYBIND11_BINARY_OPERATOR(ne, ne, operator!=, l != r)
|
||||
PYBIND11_BINARY_OPERATOR(or, ror, operator|, l | r)
|
||||
PYBIND11_BINARY_OPERATOR(gt, lt, operator>, l > r)
|
||||
PYBIND11_BINARY_OPERATOR(ge, le, operator>=, l >= r)
|
||||
PYBIND11_BINARY_OPERATOR(lt, gt, operator<, l < r)
|
||||
PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r)
|
||||
// PYBIND11_BINARY_OPERATOR(pow, rpow, pow, std::pow(l, r))
|
||||
PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r)
|
||||
PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r)
|
||||
PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r)
|
||||
PYBIND11_INPLACE_OPERATOR(itruediv, operator/=, l /= r)
|
||||
PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r)
|
||||
PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r)
|
||||
PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r)
|
||||
PYBIND11_INPLACE_OPERATOR(iand, operator&=, l &= r)
|
||||
PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r)
|
||||
PYBIND11_INPLACE_OPERATOR(ior, operator|=, l |= r)
|
||||
PYBIND11_UNARY_OPERATOR(neg, operator-, -l)
|
||||
PYBIND11_UNARY_OPERATOR(pos, operator+, +l)
|
||||
// WARNING: This usage of `abs` should only be done for existing STL overloads.
|
||||
// Adding overloads directly in to the `std::` namespace is advised against:
|
||||
// https://en.cppreference.com/w/cpp/language/extending_std
|
||||
PYBIND11_UNARY_OPERATOR(abs, abs, std::abs(l))
|
||||
PYBIND11_UNARY_OPERATOR(hash, hash, std::hash<L>()(l))
|
||||
PYBIND11_UNARY_OPERATOR(invert, operator~, (~l))
|
||||
PYBIND11_UNARY_OPERATOR(bool, operator!, !!l)
|
||||
PYBIND11_UNARY_OPERATOR(int, int_, (int) l)
|
||||
PYBIND11_UNARY_OPERATOR(float, float_, (double) l)
|
||||
PYBIND11_UNARY_OPERATOR(abs, abs, std::abs(l))
|
||||
PYBIND11_UNARY_OPERATOR(hash, hash, std::hash<L>()(l))
|
||||
PYBIND11_UNARY_OPERATOR(invert, operator~, (~l))
|
||||
PYBIND11_UNARY_OPERATOR(bool, operator!, !!l)
|
||||
PYBIND11_UNARY_OPERATOR(int, int_, (int) l)
|
||||
PYBIND11_UNARY_OPERATOR(float, float_, (double) l)
|
||||
|
||||
#undef PYBIND11_BINARY_OPERATOR
|
||||
#undef PYBIND11_INPLACE_OPERATOR
|
||||
@ -167,7 +199,3 @@ using detail::self;
|
||||
using detail::hash;
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
41
3rdparty/pybind11/include/pybind11/options.h
vendored
41
3rdparty/pybind11/include/pybind11/options.h
vendored
@ -15,43 +15,54 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
class options {
|
||||
public:
|
||||
|
||||
// Default RAII constructor, which leaves settings as they currently are.
|
||||
options() : previous_state(global_state()) {}
|
||||
|
||||
// Class is non-copyable.
|
||||
options(const options&) = delete;
|
||||
options& operator=(const options&) = delete;
|
||||
options(const options &) = delete;
|
||||
options &operator=(const options &) = delete;
|
||||
|
||||
// Destructor, which restores settings that were in effect before.
|
||||
~options() {
|
||||
global_state() = previous_state;
|
||||
}
|
||||
~options() { global_state() = previous_state; }
|
||||
|
||||
// Setter methods (affect the global state):
|
||||
|
||||
options& disable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = false; return *this; }
|
||||
options &disable_user_defined_docstrings() & {
|
||||
global_state().show_user_defined_docstrings = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
options& enable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = true; return *this; }
|
||||
options &enable_user_defined_docstrings() & {
|
||||
global_state().show_user_defined_docstrings = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
options& disable_function_signatures() & { global_state().show_function_signatures = false; return *this; }
|
||||
options &disable_function_signatures() & {
|
||||
global_state().show_function_signatures = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
options& enable_function_signatures() & { global_state().show_function_signatures = true; return *this; }
|
||||
options &enable_function_signatures() & {
|
||||
global_state().show_function_signatures = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Getter methods (return the global state):
|
||||
|
||||
static bool show_user_defined_docstrings() { return global_state().show_user_defined_docstrings; }
|
||||
static bool show_user_defined_docstrings() {
|
||||
return global_state().show_user_defined_docstrings;
|
||||
}
|
||||
|
||||
static bool show_function_signatures() { return global_state().show_function_signatures; }
|
||||
|
||||
// This type is not meant to be allocated on the heap.
|
||||
void* operator new(size_t) = delete;
|
||||
void *operator new(size_t) = delete;
|
||||
|
||||
private:
|
||||
|
||||
struct state {
|
||||
bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings.
|
||||
bool show_function_signatures = true; //< Include auto-generated function signatures in docstrings.
|
||||
bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings.
|
||||
bool show_function_signatures = true; //< Include auto-generated function signatures
|
||||
// in docstrings.
|
||||
};
|
||||
|
||||
static state &global_state() {
|
||||
|
2392
3rdparty/pybind11/include/pybind11/pybind11.h
vendored
2392
3rdparty/pybind11/include/pybind11/pybind11.h
vendored
File diff suppressed because it is too large
Load Diff
1735
3rdparty/pybind11/include/pybind11/pytypes.h
vendored
1735
3rdparty/pybind11/include/pybind11/pytypes.h
vendored
File diff suppressed because it is too large
Load Diff
281
3rdparty/pybind11/include/pybind11/stl.h
vendored
281
3rdparty/pybind11/include/pybind11/stl.h
vendored
@ -10,42 +10,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "pybind11.h"
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include "detail/common.h"
|
||||
|
||||
#include <deque>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <valarray>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
|
||||
// See `detail/common.h` for implementation of these guards.
|
||||
#if defined(PYBIND11_HAS_OPTIONAL)
|
||||
# include <optional>
|
||||
#elif defined(PYBIND11_HAS_EXP_OPTIONAL)
|
||||
# include <experimental/optional>
|
||||
#endif
|
||||
|
||||
#ifdef __has_include
|
||||
// std::optional (but including it in c++14 mode isn't allowed)
|
||||
# if defined(PYBIND11_CPP17) && __has_include(<optional>)
|
||||
# include <optional>
|
||||
# define PYBIND11_HAS_OPTIONAL 1
|
||||
# endif
|
||||
// std::experimental::optional (but not allowed in c++11 mode)
|
||||
# if defined(PYBIND11_CPP14) && (__has_include(<experimental/optional>) && \
|
||||
!__has_include(<optional>))
|
||||
# include <experimental/optional>
|
||||
# define PYBIND11_HAS_EXP_OPTIONAL 1
|
||||
# endif
|
||||
// std::variant
|
||||
# if defined(PYBIND11_CPP17) && __has_include(<variant>)
|
||||
#if defined(PYBIND11_HAS_VARIANT)
|
||||
# include <variant>
|
||||
# define PYBIND11_HAS_VARIANT 1
|
||||
# endif
|
||||
#elif defined(_MSC_VER) && defined(PYBIND11_CPP17)
|
||||
# include <optional>
|
||||
# include <variant>
|
||||
# define PYBIND11_HAS_OPTIONAL 1
|
||||
# define PYBIND11_HAS_VARIANT 1
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
@ -54,29 +38,33 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
/// Extracts an const lvalue reference or rvalue reference for U based on the type of T (e.g. for
|
||||
/// forwarding a container element). Typically used indirect via forwarded_type(), below.
|
||||
template <typename T, typename U>
|
||||
using forwarded_type = conditional_t<
|
||||
std::is_lvalue_reference<T>::value, remove_reference_t<U> &, remove_reference_t<U> &&>;
|
||||
using forwarded_type = conditional_t<std::is_lvalue_reference<T>::value,
|
||||
remove_reference_t<U> &,
|
||||
remove_reference_t<U> &&>;
|
||||
|
||||
/// Forwards a value U as rvalue or lvalue according to whether T is rvalue or lvalue; typically
|
||||
/// used for forwarding a container's elements.
|
||||
template <typename T, typename U>
|
||||
forwarded_type<T, U> forward_like(U &&u) {
|
||||
constexpr forwarded_type<T, U> forward_like(U &&u) {
|
||||
return std::forward<detail::forwarded_type<T, U>>(std::forward<U>(u));
|
||||
}
|
||||
|
||||
template <typename Type, typename Key> struct set_caster {
|
||||
template <typename Type, typename Key>
|
||||
struct set_caster {
|
||||
using type = Type;
|
||||
using key_conv = make_caster<Key>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<pybind11::set>(src))
|
||||
if (!isinstance<anyset>(src)) {
|
||||
return false;
|
||||
auto s = reinterpret_borrow<pybind11::set>(src);
|
||||
}
|
||||
auto s = reinterpret_borrow<anyset>(src);
|
||||
value.clear();
|
||||
for (auto entry : s) {
|
||||
key_conv conv;
|
||||
if (!conv.load(entry, convert))
|
||||
if (!conv.load(entry, convert)) {
|
||||
return false;
|
||||
}
|
||||
value.insert(cast_op<Key &&>(std::move(conv)));
|
||||
}
|
||||
return true;
|
||||
@ -84,35 +72,40 @@ template <typename Type, typename Key> struct set_caster {
|
||||
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!std::is_lvalue_reference<T>::value)
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Key>::policy(policy);
|
||||
}
|
||||
pybind11::set s;
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(key_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_ || !s.add(value_))
|
||||
auto value_ = reinterpret_steal<object>(
|
||||
key_conv::cast(detail::forward_like<T>(value), policy, parent));
|
||||
if (!value_ || !s.add(std::move(value_))) {
|
||||
return handle();
|
||||
}
|
||||
}
|
||||
return s.release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(type, _("Set[") + key_conv::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(type, const_name("Set[") + key_conv::name + const_name("]"));
|
||||
};
|
||||
|
||||
template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
using key_conv = make_caster<Key>;
|
||||
template <typename Type, typename Key, typename Value>
|
||||
struct map_caster {
|
||||
using key_conv = make_caster<Key>;
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<dict>(src))
|
||||
if (!isinstance<dict>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto d = reinterpret_borrow<dict>(src);
|
||||
value.clear();
|
||||
for (auto it : d) {
|
||||
key_conv kconv;
|
||||
value_conv vconv;
|
||||
if (!kconv.load(it.first.ptr(), convert) ||
|
||||
!vconv.load(it.second.ptr(), convert))
|
||||
if (!kconv.load(it.first.ptr(), convert) || !vconv.load(it.second.ptr(), convert)) {
|
||||
return false;
|
||||
}
|
||||
value.emplace(cast_op<Key &&>(std::move(kconv)), cast_op<Value &&>(std::move(vconv)));
|
||||
}
|
||||
return true;
|
||||
@ -128,78 +121,94 @@ template <typename Type, typename Key, typename Value> struct map_caster {
|
||||
policy_value = return_value_policy_override<Value>::policy(policy_value);
|
||||
}
|
||||
for (auto &&kv : src) {
|
||||
auto key = reinterpret_steal<object>(key_conv::cast(forward_like<T>(kv.first), policy_key, parent));
|
||||
auto value = reinterpret_steal<object>(value_conv::cast(forward_like<T>(kv.second), policy_value, parent));
|
||||
if (!key || !value)
|
||||
auto key = reinterpret_steal<object>(
|
||||
key_conv::cast(detail::forward_like<T>(kv.first), policy_key, parent));
|
||||
auto value = reinterpret_steal<object>(
|
||||
value_conv::cast(detail::forward_like<T>(kv.second), policy_value, parent));
|
||||
if (!key || !value) {
|
||||
return handle();
|
||||
d[key] = value;
|
||||
}
|
||||
d[std::move(key)] = std::move(value);
|
||||
}
|
||||
return d.release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(Type, _("Dict[") + key_conv::name + _(", ") + value_conv::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(Type,
|
||||
const_name("Dict[") + key_conv::name + const_name(", ") + value_conv::name
|
||||
+ const_name("]"));
|
||||
};
|
||||
|
||||
template <typename Type, typename Value> struct list_caster {
|
||||
template <typename Type, typename Value>
|
||||
struct list_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<sequence>(src) || isinstance<str>(src))
|
||||
if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto s = reinterpret_borrow<sequence>(src);
|
||||
value.clear();
|
||||
reserve_maybe(s, &value);
|
||||
for (auto it : s) {
|
||||
value_conv conv;
|
||||
if (!conv.load(it, convert))
|
||||
if (!conv.load(it, convert)) {
|
||||
return false;
|
||||
}
|
||||
value.push_back(cast_op<Value &&>(std::move(conv)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T = Type,
|
||||
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
|
||||
void reserve_maybe(sequence s, Type *) { value.reserve(s.size()); }
|
||||
void reserve_maybe(sequence, void *) { }
|
||||
template <
|
||||
typename T = Type,
|
||||
enable_if_t<std::is_same<decltype(std::declval<T>().reserve(0)), void>::value, int> = 0>
|
||||
void reserve_maybe(const sequence &s, Type *) {
|
||||
value.reserve(s.size());
|
||||
}
|
||||
void reserve_maybe(const sequence &, void *) {}
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!std::is_lvalue_reference<T>::value)
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
list l(src.size());
|
||||
size_t index = 0;
|
||||
ssize_t index = 0;
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_)
|
||||
auto value_ = reinterpret_steal<object>(
|
||||
value_conv::cast(detail::forward_like<T>(value), policy, parent));
|
||||
if (!value_) {
|
||||
return handle();
|
||||
PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference
|
||||
}
|
||||
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||
}
|
||||
return l.release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(Type, _("List[") + value_conv::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(Type, const_name("List[") + value_conv::name + const_name("]"));
|
||||
};
|
||||
|
||||
template <typename Type, typename Alloc> struct type_caster<std::vector<Type, Alloc>>
|
||||
: list_caster<std::vector<Type, Alloc>, Type> { };
|
||||
template <typename Type, typename Alloc>
|
||||
struct type_caster<std::vector<Type, Alloc>> : list_caster<std::vector<Type, Alloc>, Type> {};
|
||||
|
||||
template <typename Type, typename Alloc> struct type_caster<std::deque<Type, Alloc>>
|
||||
: list_caster<std::deque<Type, Alloc>, Type> { };
|
||||
template <typename Type, typename Alloc>
|
||||
struct type_caster<std::deque<Type, Alloc>> : list_caster<std::deque<Type, Alloc>, Type> {};
|
||||
|
||||
template <typename Type, typename Alloc> struct type_caster<std::list<Type, Alloc>>
|
||||
: list_caster<std::list<Type, Alloc>, Type> { };
|
||||
template <typename Type, typename Alloc>
|
||||
struct type_caster<std::list<Type, Alloc>> : list_caster<std::list<Type, Alloc>, Type> {};
|
||||
|
||||
template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0> struct array_caster {
|
||||
template <typename ArrayType, typename Value, bool Resizable, size_t Size = 0>
|
||||
struct array_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
private:
|
||||
template <bool R = Resizable>
|
||||
bool require_size(enable_if_t<R, size_t> size) {
|
||||
if (value.size() != size)
|
||||
if (value.size() != size) {
|
||||
value.resize(size);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <bool R = Resizable>
|
||||
@ -209,16 +218,19 @@ private:
|
||||
|
||||
public:
|
||||
bool load(handle src, bool convert) {
|
||||
if (!isinstance<sequence>(src))
|
||||
if (!isinstance<sequence>(src)) {
|
||||
return false;
|
||||
}
|
||||
auto l = reinterpret_borrow<sequence>(src);
|
||||
if (!require_size(l.size()))
|
||||
if (!require_size(l.size())) {
|
||||
return false;
|
||||
}
|
||||
size_t ctr = 0;
|
||||
for (auto it : l) {
|
||||
value_conv conv;
|
||||
if (!conv.load(it, convert))
|
||||
if (!conv.load(it, convert)) {
|
||||
return false;
|
||||
}
|
||||
value[ctr++] = cast_op<Value &&>(std::move(conv));
|
||||
}
|
||||
return true;
|
||||
@ -227,81 +239,99 @@ public:
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
list l(src.size());
|
||||
size_t index = 0;
|
||||
ssize_t index = 0;
|
||||
for (auto &&value : src) {
|
||||
auto value_ = reinterpret_steal<object>(value_conv::cast(forward_like<T>(value), policy, parent));
|
||||
if (!value_)
|
||||
auto value_ = reinterpret_steal<object>(
|
||||
value_conv::cast(detail::forward_like<T>(value), policy, parent));
|
||||
if (!value_) {
|
||||
return handle();
|
||||
PyList_SET_ITEM(l.ptr(), (ssize_t) index++, value_.release().ptr()); // steals a reference
|
||||
}
|
||||
PyList_SET_ITEM(l.ptr(), index++, value_.release().ptr()); // steals a reference
|
||||
}
|
||||
return l.release();
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(ArrayType, _("List[") + value_conv::name + _<Resizable>(_(""), _("[") + _<Size>() + _("]")) + _("]"));
|
||||
PYBIND11_TYPE_CASTER(ArrayType,
|
||||
const_name("List[") + value_conv::name
|
||||
+ const_name<Resizable>(const_name(""),
|
||||
const_name("[") + const_name<Size>()
|
||||
+ const_name("]"))
|
||||
+ const_name("]"));
|
||||
};
|
||||
|
||||
template <typename Type, size_t Size> struct type_caster<std::array<Type, Size>>
|
||||
: array_caster<std::array<Type, Size>, Type, false, Size> { };
|
||||
template <typename Type, size_t Size>
|
||||
struct type_caster<std::array<Type, Size>>
|
||||
: array_caster<std::array<Type, Size>, Type, false, Size> {};
|
||||
|
||||
template <typename Type> struct type_caster<std::valarray<Type>>
|
||||
: array_caster<std::valarray<Type>, Type, true> { };
|
||||
template <typename Type>
|
||||
struct type_caster<std::valarray<Type>> : array_caster<std::valarray<Type>, Type, true> {};
|
||||
|
||||
template <typename Key, typename Compare, typename Alloc> struct type_caster<std::set<Key, Compare, Alloc>>
|
||||
: set_caster<std::set<Key, Compare, Alloc>, Key> { };
|
||||
template <typename Key, typename Compare, typename Alloc>
|
||||
struct type_caster<std::set<Key, Compare, Alloc>>
|
||||
: set_caster<std::set<Key, Compare, Alloc>, Key> {};
|
||||
|
||||
template <typename Key, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
|
||||
: set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> { };
|
||||
template <typename Key, typename Hash, typename Equal, typename Alloc>
|
||||
struct type_caster<std::unordered_set<Key, Hash, Equal, Alloc>>
|
||||
: set_caster<std::unordered_set<Key, Hash, Equal, Alloc>, Key> {};
|
||||
|
||||
template <typename Key, typename Value, typename Compare, typename Alloc> struct type_caster<std::map<Key, Value, Compare, Alloc>>
|
||||
: map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> { };
|
||||
template <typename Key, typename Value, typename Compare, typename Alloc>
|
||||
struct type_caster<std::map<Key, Value, Compare, Alloc>>
|
||||
: map_caster<std::map<Key, Value, Compare, Alloc>, Key, Value> {};
|
||||
|
||||
template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc> struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
|
||||
: map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> { };
|
||||
template <typename Key, typename Value, typename Hash, typename Equal, typename Alloc>
|
||||
struct type_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>>
|
||||
: map_caster<std::unordered_map<Key, Value, Hash, Equal, Alloc>, Key, Value> {};
|
||||
|
||||
// This type caster is intended to be used for std::optional and std::experimental::optional
|
||||
template<typename T> struct optional_caster {
|
||||
using value_conv = make_caster<typename T::value_type>;
|
||||
template <typename Type, typename Value = typename Type::value_type>
|
||||
struct optional_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
template <typename T_>
|
||||
static handle cast(T_ &&src, return_value_policy policy, handle parent) {
|
||||
if (!src)
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!src) {
|
||||
return none().inc_ref();
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<T>::policy(policy);
|
||||
}
|
||||
return value_conv::cast(*std::forward<T_>(src), policy, parent);
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
return value_conv::cast(*std::forward<T>(src), policy, parent);
|
||||
}
|
||||
|
||||
bool load(handle src, bool convert) {
|
||||
if (!src) {
|
||||
return false;
|
||||
} else if (src.is_none()) {
|
||||
return true; // default-constructed value is already empty
|
||||
}
|
||||
if (src.is_none()) {
|
||||
return true; // default-constructed value is already empty
|
||||
}
|
||||
value_conv inner_caster;
|
||||
if (!inner_caster.load(src, convert))
|
||||
if (!inner_caster.load(src, convert)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value.emplace(cast_op<typename T::value_type &&>(std::move(inner_caster)));
|
||||
value.emplace(cast_op<Value &&>(std::move(inner_caster)));
|
||||
return true;
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(T, _("Optional[") + value_conv::name + _("]"));
|
||||
PYBIND11_TYPE_CASTER(Type, const_name("Optional[") + value_conv::name + const_name("]"));
|
||||
};
|
||||
|
||||
#if defined(PYBIND11_HAS_OPTIONAL)
|
||||
template<typename T> struct type_caster<std::optional<T>>
|
||||
: public optional_caster<std::optional<T>> {};
|
||||
template <typename T>
|
||||
struct type_caster<std::optional<T>> : public optional_caster<std::optional<T>> {};
|
||||
|
||||
template<> struct type_caster<std::nullopt_t>
|
||||
: public void_caster<std::nullopt_t> {};
|
||||
template <>
|
||||
struct type_caster<std::nullopt_t> : public void_caster<std::nullopt_t> {};
|
||||
#endif
|
||||
|
||||
#if defined(PYBIND11_HAS_EXP_OPTIONAL)
|
||||
template<typename T> struct type_caster<std::experimental::optional<T>>
|
||||
template <typename T>
|
||||
struct type_caster<std::experimental::optional<T>>
|
||||
: public optional_caster<std::experimental::optional<T>> {};
|
||||
|
||||
template<> struct type_caster<std::experimental::nullopt_t>
|
||||
template <>
|
||||
struct type_caster<std::experimental::nullopt_t>
|
||||
: public void_caster<std::experimental::nullopt_t> {};
|
||||
#endif
|
||||
|
||||
@ -322,7 +352,7 @@ struct variant_caster_visitor {
|
||||
/// `namespace::variant` types which provide a `namespace::visit()` function are handled here
|
||||
/// automatically using argument-dependent lookup. Users can provide specializations for other
|
||||
/// variant-like classes, e.g. `boost::variant` and `boost::apply_visitor`.
|
||||
template <template<typename...> class Variant>
|
||||
template <template <typename...> class Variant>
|
||||
struct visit_helper {
|
||||
template <typename... Args>
|
||||
static auto call(Args &&...args) -> decltype(visit(std::forward<Args>(args)...)) {
|
||||
@ -331,9 +361,10 @@ struct visit_helper {
|
||||
};
|
||||
|
||||
/// Generic variant caster
|
||||
template <typename Variant> struct variant_caster;
|
||||
template <typename Variant>
|
||||
struct variant_caster;
|
||||
|
||||
template <template<typename...> class V, typename... Ts>
|
||||
template <template <typename...> class V, typename... Ts>
|
||||
struct variant_caster<V<Ts...>> {
|
||||
static_assert(sizeof...(Ts) > 0, "Variant must consist of at least one alternative.");
|
||||
|
||||
@ -341,7 +372,7 @@ struct variant_caster<V<Ts...>> {
|
||||
bool load_alternative(handle src, bool convert, type_list<U, Us...>) {
|
||||
auto caster = make_caster<U>();
|
||||
if (caster.load(src, convert)) {
|
||||
value = cast_op<U>(caster);
|
||||
value = cast_op<U>(std::move(caster));
|
||||
return true;
|
||||
}
|
||||
return load_alternative(src, convert, type_list<Us...>{});
|
||||
@ -354,8 +385,9 @@ struct variant_caster<V<Ts...>> {
|
||||
// E.g. `py::int_(1).cast<variant<double, int>>()` needs to fill the `int`
|
||||
// slot of the variant. Without two-pass loading `double` would be filled
|
||||
// because it appears first and a conversion is possible.
|
||||
if (convert && load_alternative(src, false, type_list<Ts...>{}))
|
||||
if (convert && load_alternative(src, false, type_list<Ts...>{})) {
|
||||
return true;
|
||||
}
|
||||
return load_alternative(src, convert, type_list<Ts...>{});
|
||||
}
|
||||
|
||||
@ -366,23 +398,28 @@ struct variant_caster<V<Ts...>> {
|
||||
}
|
||||
|
||||
using Type = V<Ts...>;
|
||||
PYBIND11_TYPE_CASTER(Type, _("Union[") + detail::concat(make_caster<Ts>::name...) + _("]"));
|
||||
PYBIND11_TYPE_CASTER(Type,
|
||||
const_name("Union[") + detail::concat(make_caster<Ts>::name...)
|
||||
+ const_name("]"));
|
||||
};
|
||||
|
||||
#if defined(PYBIND11_HAS_VARIANT)
|
||||
template <typename... Ts>
|
||||
struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> { };
|
||||
struct type_caster<std::variant<Ts...>> : variant_caster<std::variant<Ts...>> {};
|
||||
|
||||
template <>
|
||||
struct type_caster<std::monostate> : public void_caster<std::monostate> {};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &os, const handle &obj) {
|
||||
#ifdef PYBIND11_HAS_STRING_VIEW
|
||||
os << str(obj).cast<std::string_view>();
|
||||
#else
|
||||
os << (std::string) str(obj);
|
||||
#endif
|
||||
return os;
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
116
3rdparty/pybind11/include/pybind11/stl/filesystem.h
vendored
Normal file
116
3rdparty/pybind11/include/pybind11/stl/filesystem.h
vendored
Normal file
@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2021 The Pybind Development Team.
|
||||
// All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../pybind11.h"
|
||||
#include "../detail/common.h"
|
||||
#include "../detail/descr.h"
|
||||
#include "../cast.h"
|
||||
#include "../pytypes.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __has_include
|
||||
# if defined(PYBIND11_CPP17)
|
||||
# if __has_include(<filesystem>) && \
|
||||
PY_VERSION_HEX >= 0x03060000
|
||||
# include <filesystem>
|
||||
# define PYBIND11_HAS_FILESYSTEM 1
|
||||
# elif __has_include(<experimental/filesystem>)
|
||||
# include <experimental/filesystem>
|
||||
# define PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM 1
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if !defined(PYBIND11_HAS_FILESYSTEM) && !defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM) \
|
||||
&& !defined(PYBIND11_HAS_FILESYSTEM_IS_OPTIONAL)
|
||||
# error \
|
||||
"Neither #include <filesystem> nor #include <experimental/filesystem is available. (Use -DPYBIND11_HAS_FILESYSTEM_IS_OPTIONAL to ignore.)"
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
#if defined(PYBIND11_HAS_FILESYSTEM) || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||
template <typename T>
|
||||
struct path_caster {
|
||||
|
||||
private:
|
||||
static PyObject *unicode_from_fs_native(const std::string &w) {
|
||||
# if !defined(PYPY_VERSION)
|
||||
return PyUnicode_DecodeFSDefaultAndSize(w.c_str(), ssize_t(w.size()));
|
||||
# else
|
||||
// PyPy mistakenly declares the first parameter as non-const.
|
||||
return PyUnicode_DecodeFSDefaultAndSize(const_cast<char *>(w.c_str()), ssize_t(w.size()));
|
||||
# endif
|
||||
}
|
||||
|
||||
static PyObject *unicode_from_fs_native(const std::wstring &w) {
|
||||
return PyUnicode_FromWideChar(w.c_str(), ssize_t(w.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
static handle cast(const T &path, return_value_policy, handle) {
|
||||
if (auto py_str = unicode_from_fs_native(path.native())) {
|
||||
return module_::import("pathlib")
|
||||
.attr("Path")(reinterpret_steal<object>(py_str))
|
||||
.release();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool load(handle handle, bool) {
|
||||
// PyUnicode_FSConverter and PyUnicode_FSDecoder normally take care of
|
||||
// calling PyOS_FSPath themselves, but that's broken on PyPy (PyPy
|
||||
// issue #3168) so we do it ourselves instead.
|
||||
PyObject *buf = PyOS_FSPath(handle.ptr());
|
||||
if (!buf) {
|
||||
PyErr_Clear();
|
||||
return false;
|
||||
}
|
||||
PyObject *native = nullptr;
|
||||
if constexpr (std::is_same_v<typename T::value_type, char>) {
|
||||
if (PyUnicode_FSConverter(buf, &native) != 0) {
|
||||
if (auto *c_str = PyBytes_AsString(native)) {
|
||||
// AsString returns a pointer to the internal buffer, which
|
||||
// must not be free'd.
|
||||
value = c_str;
|
||||
}
|
||||
}
|
||||
} else if constexpr (std::is_same_v<typename T::value_type, wchar_t>) {
|
||||
if (PyUnicode_FSDecoder(buf, &native) != 0) {
|
||||
if (auto *c_str = PyUnicode_AsWideCharString(native, nullptr)) {
|
||||
// AsWideCharString returns a new string that must be free'd.
|
||||
value = c_str; // Copies the string.
|
||||
PyMem_Free(c_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_XDECREF(native);
|
||||
Py_DECREF(buf);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Clear();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
PYBIND11_TYPE_CASTER(T, const_name("os.PathLike"));
|
||||
};
|
||||
|
||||
#endif // PYBIND11_HAS_FILESYSTEM || defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||
|
||||
#if defined(PYBIND11_HAS_FILESYSTEM)
|
||||
template <>
|
||||
struct type_caster<std::filesystem::path> : public path_caster<std::filesystem::path> {};
|
||||
#elif defined(PYBIND11_HAS_EXPERIMENTAL_FILESYSTEM)
|
||||
template <>
|
||||
struct type_caster<std::experimental::filesystem::path>
|
||||
: public path_caster<std::experimental::filesystem::path> {};
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
670
3rdparty/pybind11/include/pybind11/stl_bind.h
vendored
670
3rdparty/pybind11/include/pybind11/stl_bind.h
vendored
@ -19,254 +19,274 @@ PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
/* SFINAE helper class used by 'is_comparable */
|
||||
template <typename T> struct container_traits {
|
||||
template <typename T2> static std::true_type test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>())*);
|
||||
template <typename T2> static std::false_type test_comparable(...);
|
||||
template <typename T2> static std::true_type test_value(typename T2::value_type *);
|
||||
template <typename T2> static std::false_type test_value(...);
|
||||
template <typename T2> static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
|
||||
template <typename T2> static std::false_type test_pair(...);
|
||||
template <typename T>
|
||||
struct container_traits {
|
||||
template <typename T2>
|
||||
static std::true_type
|
||||
test_comparable(decltype(std::declval<const T2 &>() == std::declval<const T2 &>()) *);
|
||||
template <typename T2>
|
||||
static std::false_type test_comparable(...);
|
||||
template <typename T2>
|
||||
static std::true_type test_value(typename T2::value_type *);
|
||||
template <typename T2>
|
||||
static std::false_type test_value(...);
|
||||
template <typename T2>
|
||||
static std::true_type test_pair(typename T2::first_type *, typename T2::second_type *);
|
||||
template <typename T2>
|
||||
static std::false_type test_pair(...);
|
||||
|
||||
static constexpr const bool is_comparable = std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
|
||||
static constexpr const bool is_pair = std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
|
||||
static constexpr const bool is_vector = std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
|
||||
static constexpr const bool is_comparable
|
||||
= std::is_same<std::true_type, decltype(test_comparable<T>(nullptr))>::value;
|
||||
static constexpr const bool is_pair
|
||||
= std::is_same<std::true_type, decltype(test_pair<T>(nullptr, nullptr))>::value;
|
||||
static constexpr const bool is_vector
|
||||
= std::is_same<std::true_type, decltype(test_value<T>(nullptr))>::value;
|
||||
static constexpr const bool is_element = !is_pair && !is_vector;
|
||||
};
|
||||
|
||||
/* Default: is_comparable -> std::false_type */
|
||||
template <typename T, typename SFINAE = void>
|
||||
struct is_comparable : std::false_type { };
|
||||
struct is_comparable : std::false_type {};
|
||||
|
||||
/* For non-map data structures, check whether operator== can be instantiated */
|
||||
template <typename T>
|
||||
struct is_comparable<
|
||||
T, enable_if_t<container_traits<T>::is_element &&
|
||||
container_traits<T>::is_comparable>>
|
||||
: std::true_type { };
|
||||
T,
|
||||
enable_if_t<container_traits<T>::is_element && container_traits<T>::is_comparable>>
|
||||
: std::true_type {};
|
||||
|
||||
/* For a vector/map data structure, recursively check the value type (which is std::pair for maps) */
|
||||
/* For a vector/map data structure, recursively check the value type
|
||||
(which is std::pair for maps) */
|
||||
template <typename T>
|
||||
struct is_comparable<T, enable_if_t<container_traits<T>::is_vector>> {
|
||||
static constexpr const bool value =
|
||||
is_comparable<typename T::value_type>::value;
|
||||
static constexpr const bool value = is_comparable<typename T::value_type>::value;
|
||||
};
|
||||
|
||||
/* For pairs, recursively check the two data types */
|
||||
template <typename T>
|
||||
struct is_comparable<T, enable_if_t<container_traits<T>::is_pair>> {
|
||||
static constexpr const bool value =
|
||||
is_comparable<typename T::first_type>::value &&
|
||||
is_comparable<typename T::second_type>::value;
|
||||
static constexpr const bool value = is_comparable<typename T::first_type>::value
|
||||
&& is_comparable<typename T::second_type>::value;
|
||||
};
|
||||
|
||||
/* Fallback functions */
|
||||
template <typename, typename, typename... Args> void vector_if_copy_constructible(const Args &...) { }
|
||||
template <typename, typename, typename... Args> void vector_if_equal_operator(const Args &...) { }
|
||||
template <typename, typename, typename... Args> void vector_if_insertion_operator(const Args &...) { }
|
||||
template <typename, typename, typename... Args> void vector_modifiers(const Args &...) { }
|
||||
template <typename, typename, typename... Args>
|
||||
void vector_if_copy_constructible(const Args &...) {}
|
||||
template <typename, typename, typename... Args>
|
||||
void vector_if_equal_operator(const Args &...) {}
|
||||
template <typename, typename, typename... Args>
|
||||
void vector_if_insertion_operator(const Args &...) {}
|
||||
template <typename, typename, typename... Args>
|
||||
void vector_modifiers(const Args &...) {}
|
||||
|
||||
template<typename Vector, typename Class_>
|
||||
template <typename Vector, typename Class_>
|
||||
void vector_if_copy_constructible(enable_if_t<is_copy_constructible<Vector>::value, Class_> &cl) {
|
||||
cl.def(init<const Vector &>(), "Copy constructor");
|
||||
}
|
||||
|
||||
template<typename Vector, typename Class_>
|
||||
template <typename Vector, typename Class_>
|
||||
void vector_if_equal_operator(enable_if_t<is_comparable<Vector>::value, Class_> &cl) {
|
||||
using T = typename Vector::value_type;
|
||||
|
||||
cl.def(self == self);
|
||||
cl.def(self != self);
|
||||
|
||||
cl.def("count",
|
||||
[](const Vector &v, const T &x) {
|
||||
return std::count(v.begin(), v.end(), x);
|
||||
},
|
||||
cl.def(
|
||||
"count",
|
||||
[](const Vector &v, const T &x) { return std::count(v.begin(), v.end(), x); },
|
||||
arg("x"),
|
||||
"Return the number of times ``x`` appears in the list"
|
||||
);
|
||||
"Return the number of times ``x`` appears in the list");
|
||||
|
||||
cl.def("remove", [](Vector &v, const T &x) {
|
||||
cl.def(
|
||||
"remove",
|
||||
[](Vector &v, const T &x) {
|
||||
auto p = std::find(v.begin(), v.end(), x);
|
||||
if (p != v.end())
|
||||
if (p != v.end()) {
|
||||
v.erase(p);
|
||||
else
|
||||
} else {
|
||||
throw value_error();
|
||||
}
|
||||
},
|
||||
arg("x"),
|
||||
"Remove the first item from the list whose value is x. "
|
||||
"It is an error if there is no such item."
|
||||
);
|
||||
"It is an error if there is no such item.");
|
||||
|
||||
cl.def("__contains__",
|
||||
[](const Vector &v, const T &x) {
|
||||
return std::find(v.begin(), v.end(), x) != v.end();
|
||||
},
|
||||
cl.def(
|
||||
"__contains__",
|
||||
[](const Vector &v, const T &x) { return std::find(v.begin(), v.end(), x) != v.end(); },
|
||||
arg("x"),
|
||||
"Return true the container contains ``x``"
|
||||
);
|
||||
"Return true the container contains ``x``");
|
||||
}
|
||||
|
||||
// Vector modifiers -- requires a copyable vector_type:
|
||||
// (Technically, some of these (pop and __delitem__) don't actually require copyability, but it seems
|
||||
// silly to allow deletion but not insertion, so include them here too.)
|
||||
// (Technically, some of these (pop and __delitem__) don't actually require copyability, but it
|
||||
// seems silly to allow deletion but not insertion, so include them here too.)
|
||||
template <typename Vector, typename Class_>
|
||||
void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
|
||||
void vector_modifiers(
|
||||
enable_if_t<is_copy_constructible<typename Vector::value_type>::value, Class_> &cl) {
|
||||
using T = typename Vector::value_type;
|
||||
using SizeType = typename Vector::size_type;
|
||||
using DiffType = typename Vector::difference_type;
|
||||
|
||||
auto wrap_i = [](DiffType i, SizeType n) {
|
||||
if (i < 0)
|
||||
if (i < 0) {
|
||||
i += n;
|
||||
if (i < 0 || (SizeType)i >= n)
|
||||
}
|
||||
if (i < 0 || (SizeType) i >= n) {
|
||||
throw index_error();
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
cl.def("append",
|
||||
[](Vector &v, const T &value) { v.push_back(value); },
|
||||
arg("x"),
|
||||
"Add an item to the end of the list");
|
||||
cl.def(
|
||||
"append",
|
||||
[](Vector &v, const T &value) { v.push_back(value); },
|
||||
arg("x"),
|
||||
"Add an item to the end of the list");
|
||||
|
||||
cl.def(init([](iterable it) {
|
||||
cl.def(init([](const iterable &it) {
|
||||
auto v = std::unique_ptr<Vector>(new Vector());
|
||||
v->reserve(len_hint(it));
|
||||
for (handle h : it)
|
||||
v->push_back(h.cast<T>());
|
||||
for (handle h : it) {
|
||||
v->push_back(h.cast<T>());
|
||||
}
|
||||
return v.release();
|
||||
}));
|
||||
|
||||
cl.def("clear",
|
||||
[](Vector &v) {
|
||||
v.clear();
|
||||
cl.def(
|
||||
"clear", [](Vector &v) { v.clear(); }, "Clear the contents");
|
||||
|
||||
cl.def(
|
||||
"extend",
|
||||
[](Vector &v, const Vector &src) { v.insert(v.end(), src.begin(), src.end()); },
|
||||
arg("L"),
|
||||
"Extend the list by appending all the items in the given list");
|
||||
|
||||
cl.def(
|
||||
"extend",
|
||||
[](Vector &v, const iterable &it) {
|
||||
const size_t old_size = v.size();
|
||||
v.reserve(old_size + len_hint(it));
|
||||
try {
|
||||
for (handle h : it) {
|
||||
v.push_back(h.cast<T>());
|
||||
}
|
||||
} catch (const cast_error &) {
|
||||
v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size),
|
||||
v.end());
|
||||
try {
|
||||
v.shrink_to_fit();
|
||||
} catch (const std::exception &) {
|
||||
// Do nothing
|
||||
}
|
||||
throw;
|
||||
}
|
||||
},
|
||||
"Clear the contents"
|
||||
);
|
||||
arg("L"),
|
||||
"Extend the list by appending all the items in the given list");
|
||||
|
||||
cl.def("extend",
|
||||
[](Vector &v, const Vector &src) {
|
||||
v.insert(v.end(), src.begin(), src.end());
|
||||
},
|
||||
arg("L"),
|
||||
"Extend the list by appending all the items in the given list"
|
||||
);
|
||||
|
||||
cl.def("extend",
|
||||
[](Vector &v, iterable it) {
|
||||
const size_t old_size = v.size();
|
||||
v.reserve(old_size + len_hint(it));
|
||||
try {
|
||||
for (handle h : it) {
|
||||
v.push_back(h.cast<T>());
|
||||
}
|
||||
} catch (const cast_error &) {
|
||||
v.erase(v.begin() + static_cast<typename Vector::difference_type>(old_size), v.end());
|
||||
try {
|
||||
v.shrink_to_fit();
|
||||
} catch (const std::exception &) {
|
||||
// Do nothing
|
||||
}
|
||||
throw;
|
||||
}
|
||||
},
|
||||
arg("L"),
|
||||
"Extend the list by appending all the items in the given list"
|
||||
);
|
||||
|
||||
cl.def("insert",
|
||||
cl.def(
|
||||
"insert",
|
||||
[](Vector &v, DiffType i, const T &x) {
|
||||
// Can't use wrap_i; i == v.size() is OK
|
||||
if (i < 0)
|
||||
if (i < 0) {
|
||||
i += v.size();
|
||||
if (i < 0 || (SizeType)i > v.size())
|
||||
}
|
||||
if (i < 0 || (SizeType) i > v.size()) {
|
||||
throw index_error();
|
||||
}
|
||||
v.insert(v.begin() + i, x);
|
||||
},
|
||||
arg("i") , arg("x"),
|
||||
"Insert an item at a given position."
|
||||
);
|
||||
arg("i"),
|
||||
arg("x"),
|
||||
"Insert an item at a given position.");
|
||||
|
||||
cl.def("pop",
|
||||
cl.def(
|
||||
"pop",
|
||||
[](Vector &v) {
|
||||
if (v.empty())
|
||||
if (v.empty()) {
|
||||
throw index_error();
|
||||
T t = v.back();
|
||||
}
|
||||
T t = std::move(v.back());
|
||||
v.pop_back();
|
||||
return t;
|
||||
},
|
||||
"Remove and return the last item"
|
||||
);
|
||||
"Remove and return the last item");
|
||||
|
||||
cl.def("pop",
|
||||
cl.def(
|
||||
"pop",
|
||||
[wrap_i](Vector &v, DiffType i) {
|
||||
i = wrap_i(i, v.size());
|
||||
T t = v[(SizeType) i];
|
||||
v.erase(v.begin() + i);
|
||||
T t = std::move(v[(SizeType) i]);
|
||||
v.erase(std::next(v.begin(), i));
|
||||
return t;
|
||||
},
|
||||
arg("i"),
|
||||
"Remove and return the item at index ``i``"
|
||||
);
|
||||
"Remove and return the item at index ``i``");
|
||||
|
||||
cl.def("__setitem__",
|
||||
[wrap_i](Vector &v, DiffType i, const T &t) {
|
||||
i = wrap_i(i, v.size());
|
||||
v[(SizeType)i] = t;
|
||||
}
|
||||
);
|
||||
cl.def("__setitem__", [wrap_i](Vector &v, DiffType i, const T &t) {
|
||||
i = wrap_i(i, v.size());
|
||||
v[(SizeType) i] = t;
|
||||
});
|
||||
|
||||
/// Slicing protocol
|
||||
cl.def("__getitem__",
|
||||
[](const Vector &v, slice slice) -> Vector * {
|
||||
size_t start, stop, step, slicelength;
|
||||
cl.def(
|
||||
"__getitem__",
|
||||
[](const Vector &v, const slice &slice) -> Vector * {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
auto *seq = new Vector();
|
||||
seq->reserve((size_t) slicelength);
|
||||
|
||||
for (size_t i=0; i<slicelength; ++i) {
|
||||
for (size_t i = 0; i < slicelength; ++i) {
|
||||
seq->push_back(v[start]);
|
||||
start += step;
|
||||
}
|
||||
return seq;
|
||||
},
|
||||
arg("s"),
|
||||
"Retrieve list elements using a slice object"
|
||||
);
|
||||
"Retrieve list elements using a slice object");
|
||||
|
||||
cl.def("__setitem__",
|
||||
[](Vector &v, slice slice, const Vector &value) {
|
||||
size_t start, stop, step, slicelength;
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
|
||||
cl.def(
|
||||
"__setitem__",
|
||||
[](Vector &v, const slice &slice, const Vector &value) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
if (slicelength != value.size())
|
||||
throw std::runtime_error("Left and right hand size of slice assignment have different sizes!");
|
||||
if (slicelength != value.size()) {
|
||||
throw std::runtime_error(
|
||||
"Left and right hand size of slice assignment have different sizes!");
|
||||
}
|
||||
|
||||
for (size_t i=0; i<slicelength; ++i) {
|
||||
for (size_t i = 0; i < slicelength; ++i) {
|
||||
v[start] = value[i];
|
||||
start += step;
|
||||
}
|
||||
},
|
||||
"Assign list elements using a slice object"
|
||||
);
|
||||
"Assign list elements using a slice object");
|
||||
|
||||
cl.def("__delitem__",
|
||||
cl.def(
|
||||
"__delitem__",
|
||||
[wrap_i](Vector &v, DiffType i) {
|
||||
i = wrap_i(i, v.size());
|
||||
v.erase(v.begin() + i);
|
||||
},
|
||||
"Delete the list elements at index ``i``"
|
||||
);
|
||||
"Delete the list elements at index ``i``");
|
||||
|
||||
cl.def("__delitem__",
|
||||
[](Vector &v, slice slice) {
|
||||
size_t start, stop, step, slicelength;
|
||||
cl.def(
|
||||
"__delitem__",
|
||||
[](Vector &v, const slice &slice) {
|
||||
size_t start = 0, stop = 0, step = 0, slicelength = 0;
|
||||
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength))
|
||||
if (!slice.compute(v.size(), &start, &stop, &step, &slicelength)) {
|
||||
throw error_already_set();
|
||||
}
|
||||
|
||||
if (step == 1 && false) {
|
||||
v.erase(v.begin() + (DiffType) start, v.begin() + DiffType(start + slicelength));
|
||||
@ -277,15 +297,15 @@ void vector_modifiers(enable_if_t<is_copy_constructible<typename Vector::value_t
|
||||
}
|
||||
}
|
||||
},
|
||||
"Delete list elements using a slice object"
|
||||
);
|
||||
|
||||
"Delete list elements using a slice object");
|
||||
}
|
||||
|
||||
// If the type has an operator[] that doesn't return a reference (most notably std::vector<bool>),
|
||||
// we have to access by copying; otherwise we return by reference.
|
||||
template <typename Vector> using vector_needs_copy = negation<
|
||||
std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]), typename Vector::value_type &>>;
|
||||
template <typename Vector>
|
||||
using vector_needs_copy
|
||||
= negation<std::is_same<decltype(std::declval<Vector>()[typename Vector::size_type()]),
|
||||
typename Vector::value_type &>>;
|
||||
|
||||
// The usual case: access and iterate by reference
|
||||
template <typename Vector, typename Class_>
|
||||
@ -293,31 +313,34 @@ void vector_accessor(enable_if_t<!vector_needs_copy<Vector>::value, Class_> &cl)
|
||||
using T = typename Vector::value_type;
|
||||
using SizeType = typename Vector::size_type;
|
||||
using DiffType = typename Vector::difference_type;
|
||||
using ItType = typename Vector::iterator;
|
||||
using ItType = typename Vector::iterator;
|
||||
|
||||
auto wrap_i = [](DiffType i, SizeType n) {
|
||||
if (i < 0)
|
||||
if (i < 0) {
|
||||
i += n;
|
||||
if (i < 0 || (SizeType)i >= n)
|
||||
}
|
||||
if (i < 0 || (SizeType) i >= n) {
|
||||
throw index_error();
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
cl.def("__getitem__",
|
||||
cl.def(
|
||||
"__getitem__",
|
||||
[wrap_i](Vector &v, DiffType i) -> T & {
|
||||
i = wrap_i(i, v.size());
|
||||
return v[(SizeType)i];
|
||||
return v[(SizeType) i];
|
||||
},
|
||||
return_value_policy::reference_internal // ref + keepalive
|
||||
);
|
||||
|
||||
cl.def("__iter__",
|
||||
[](Vector &v) {
|
||||
return make_iterator<
|
||||
return_value_policy::reference_internal, ItType, ItType, T&>(
|
||||
v.begin(), v.end());
|
||||
},
|
||||
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||
cl.def(
|
||||
"__iter__",
|
||||
[](Vector &v) {
|
||||
return make_iterator<return_value_policy::reference_internal, ItType, ItType, T &>(
|
||||
v.begin(), v.end());
|
||||
},
|
||||
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||
);
|
||||
}
|
||||
|
||||
@ -327,96 +350,129 @@ void vector_accessor(enable_if_t<vector_needs_copy<Vector>::value, Class_> &cl)
|
||||
using T = typename Vector::value_type;
|
||||
using SizeType = typename Vector::size_type;
|
||||
using DiffType = typename Vector::difference_type;
|
||||
using ItType = typename Vector::iterator;
|
||||
cl.def("__getitem__",
|
||||
[](const Vector &v, DiffType i) -> T {
|
||||
if (i < 0 && (i += v.size()) < 0)
|
||||
throw index_error();
|
||||
if ((SizeType)i >= v.size())
|
||||
throw index_error();
|
||||
return v[(SizeType)i];
|
||||
using ItType = typename Vector::iterator;
|
||||
cl.def("__getitem__", [](const Vector &v, DiffType i) -> T {
|
||||
if (i < 0 && (i += v.size()) < 0) {
|
||||
throw index_error();
|
||||
}
|
||||
);
|
||||
if ((SizeType) i >= v.size()) {
|
||||
throw index_error();
|
||||
}
|
||||
return v[(SizeType) i];
|
||||
});
|
||||
|
||||
cl.def("__iter__",
|
||||
[](Vector &v) {
|
||||
return make_iterator<
|
||||
return_value_policy::copy, ItType, ItType, T>(
|
||||
v.begin(), v.end());
|
||||
},
|
||||
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||
cl.def(
|
||||
"__iter__",
|
||||
[](Vector &v) {
|
||||
return make_iterator<return_value_policy::copy, ItType, ItType, T>(v.begin(), v.end());
|
||||
},
|
||||
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||
);
|
||||
}
|
||||
|
||||
template <typename Vector, typename Class_> auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
|
||||
-> decltype(std::declval<std::ostream&>() << std::declval<typename Vector::value_type>(), void()) {
|
||||
template <typename Vector, typename Class_>
|
||||
auto vector_if_insertion_operator(Class_ &cl, std::string const &name)
|
||||
-> decltype(std::declval<std::ostream &>() << std::declval<typename Vector::value_type>(),
|
||||
void()) {
|
||||
using size_type = typename Vector::size_type;
|
||||
|
||||
cl.def("__repr__",
|
||||
[name](Vector &v) {
|
||||
cl.def(
|
||||
"__repr__",
|
||||
[name](Vector &v) {
|
||||
std::ostringstream s;
|
||||
s << name << '[';
|
||||
for (size_type i=0; i < v.size(); ++i) {
|
||||
for (size_type i = 0; i < v.size(); ++i) {
|
||||
s << v[i];
|
||||
if (i != v.size() - 1)
|
||||
if (i != v.size() - 1) {
|
||||
s << ", ";
|
||||
}
|
||||
}
|
||||
s << ']';
|
||||
return s.str();
|
||||
},
|
||||
"Return the canonical string representation of this list."
|
||||
);
|
||||
"Return the canonical string representation of this list.");
|
||||
}
|
||||
|
||||
// Provide the buffer interface for vectors if we have data() and we have a format for it
|
||||
// GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data() is insufficient, we need to check it returns an appropriate pointer
|
||||
// GCC seems to have "void std::vector<bool>::data()" - doing SFINAE on the existence of data()
|
||||
// is insufficient, we need to check it returns an appropriate pointer
|
||||
template <typename Vector, typename = void>
|
||||
struct vector_has_data_and_format : std::false_type {};
|
||||
template <typename Vector>
|
||||
struct vector_has_data_and_format<Vector, enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(), std::declval<Vector>().data()), typename Vector::value_type*>::value>> : std::true_type {};
|
||||
struct vector_has_data_and_format<
|
||||
Vector,
|
||||
enable_if_t<std::is_same<decltype(format_descriptor<typename Vector::value_type>::format(),
|
||||
std::declval<Vector>().data()),
|
||||
typename Vector::value_type *>::value>> : std::true_type {};
|
||||
|
||||
// [workaround(intel)] Separate function required here
|
||||
// Workaround as the Intel compiler does not compile the enable_if_t part below
|
||||
// (tested with icc (ICC) 2021.1 Beta 20200827)
|
||||
template <typename... Args>
|
||||
constexpr bool args_any_are_buffer() {
|
||||
return detail::any_of<std::is_same<Args, buffer_protocol>...>::value;
|
||||
}
|
||||
|
||||
// [workaround(intel)] Separate function required here
|
||||
// [workaround(msvc)] Can't use constexpr bool in return type
|
||||
|
||||
// Add the buffer interface to a vector
|
||||
template <typename Vector, typename Class_, typename... Args>
|
||||
enable_if_t<detail::any_of<std::is_same<Args, buffer_protocol>...>::value>
|
||||
vector_buffer(Class_& cl) {
|
||||
void vector_buffer_impl(Class_ &cl, std::true_type) {
|
||||
using T = typename Vector::value_type;
|
||||
|
||||
static_assert(vector_has_data_and_format<Vector>::value, "There is not an appropriate format descriptor for this vector");
|
||||
static_assert(vector_has_data_and_format<Vector>::value,
|
||||
"There is not an appropriate format descriptor for this vector");
|
||||
|
||||
// numpy.h declares this for arbitrary types, but it may raise an exception and crash hard at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here
|
||||
// numpy.h declares this for arbitrary types, but it may raise an exception and crash hard
|
||||
// at runtime if PYBIND11_NUMPY_DTYPE hasn't been called, so check here
|
||||
format_descriptor<T>::format();
|
||||
|
||||
cl.def_buffer([](Vector& v) -> buffer_info {
|
||||
return buffer_info(v.data(), static_cast<ssize_t>(sizeof(T)), format_descriptor<T>::format(), 1, {v.size()}, {sizeof(T)});
|
||||
cl.def_buffer([](Vector &v) -> buffer_info {
|
||||
return buffer_info(v.data(),
|
||||
static_cast<ssize_t>(sizeof(T)),
|
||||
format_descriptor<T>::format(),
|
||||
1,
|
||||
{v.size()},
|
||||
{sizeof(T)});
|
||||
});
|
||||
|
||||
cl.def(init([](buffer buf) {
|
||||
cl.def(init([](const buffer &buf) {
|
||||
auto info = buf.request();
|
||||
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T)))
|
||||
if (info.ndim != 1 || info.strides[0] % static_cast<ssize_t>(sizeof(T))) {
|
||||
throw type_error("Only valid 1D buffers can be copied to a vector");
|
||||
if (!detail::compare_buffer_info<T>::compare(info) || (ssize_t) sizeof(T) != info.itemsize)
|
||||
throw type_error("Format mismatch (Python: " + info.format + " C++: " + format_descriptor<T>::format() + ")");
|
||||
}
|
||||
if (!detail::compare_buffer_info<T>::compare(info)
|
||||
|| (ssize_t) sizeof(T) != info.itemsize) {
|
||||
throw type_error("Format mismatch (Python: " + info.format
|
||||
+ " C++: " + format_descriptor<T>::format() + ")");
|
||||
}
|
||||
|
||||
T *p = static_cast<T*>(info.ptr);
|
||||
T *p = static_cast<T *>(info.ptr);
|
||||
ssize_t step = info.strides[0] / static_cast<ssize_t>(sizeof(T));
|
||||
T *end = p + info.shape[0] * step;
|
||||
if (step == 1) {
|
||||
return Vector(p, end);
|
||||
}
|
||||
else {
|
||||
Vector vec;
|
||||
vec.reserve((size_t) info.shape[0]);
|
||||
for (; p != end; p += step)
|
||||
vec.push_back(*p);
|
||||
return vec;
|
||||
Vector vec;
|
||||
vec.reserve((size_t) info.shape[0]);
|
||||
for (; p != end; p += step) {
|
||||
vec.push_back(*p);
|
||||
}
|
||||
return vec;
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename Vector, typename Class_, typename... Args>
|
||||
enable_if_t<!detail::any_of<std::is_same<Args, buffer_protocol>...>::value> vector_buffer(Class_&) {}
|
||||
void vector_buffer_impl(Class_ &, std::false_type) {}
|
||||
|
||||
template <typename Vector, typename Class_, typename... Args>
|
||||
void vector_buffer(Class_ &cl) {
|
||||
vector_buffer_impl<Vector, Class_, Args...>(
|
||||
cl, detail::any_of<std::is_same<Args, buffer_protocol>...>{});
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
@ -424,13 +480,13 @@ PYBIND11_NAMESPACE_END(detail)
|
||||
// std::vector
|
||||
//
|
||||
template <typename Vector, typename holder_type = std::unique_ptr<Vector>, typename... Args>
|
||||
class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args&&... args) {
|
||||
class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, Args &&...args) {
|
||||
using Class_ = class_<Vector, holder_type>;
|
||||
|
||||
// If the value_type is unregistered (e.g. a converting type) or is itself registered
|
||||
// module-local then make the vector binding module-local as well:
|
||||
using vtype = typename Vector::value_type;
|
||||
auto vtype_info = detail::get_type_info(typeid(vtype));
|
||||
auto *vtype_info = detail::get_type_info(typeid(vtype));
|
||||
bool local = !vtype_info || vtype_info->module_local;
|
||||
|
||||
Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
|
||||
@ -455,18 +511,13 @@ class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, A
|
||||
// Accessor and iterator; return by value if copyable, otherwise we return by ref + keep-alive
|
||||
detail::vector_accessor<Vector, Class_>(cl);
|
||||
|
||||
cl.def("__bool__",
|
||||
[](const Vector &v) -> bool {
|
||||
return !v.empty();
|
||||
},
|
||||
"Check whether the list is nonempty"
|
||||
);
|
||||
cl.def(
|
||||
"__bool__",
|
||||
[](const Vector &v) -> bool { return !v.empty(); },
|
||||
"Check whether the list is nonempty");
|
||||
|
||||
cl.def("__len__", &Vector::size);
|
||||
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
// C++ style functions deprecated, leaving it here as an example
|
||||
cl.def(init<size_type>());
|
||||
@ -510,8 +561,6 @@ class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, A
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// std::map, std::unordered_map
|
||||
//
|
||||
@ -519,81 +568,104 @@ class_<Vector, holder_type> bind_vector(handle scope, std::string const &name, A
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
/* Fallback functions */
|
||||
template <typename, typename, typename... Args> void map_if_insertion_operator(const Args &...) { }
|
||||
template <typename, typename, typename... Args> void map_assignment(const Args &...) { }
|
||||
template <typename, typename, typename... Args>
|
||||
void map_if_insertion_operator(const Args &...) {}
|
||||
template <typename, typename, typename... Args>
|
||||
void map_assignment(const Args &...) {}
|
||||
|
||||
// Map assignment when copy-assignable: just copy the value
|
||||
template <typename Map, typename Class_>
|
||||
void map_assignment(enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
|
||||
void map_assignment(
|
||||
enable_if_t<is_copy_assignable<typename Map::mapped_type>::value, Class_> &cl) {
|
||||
using KeyType = typename Map::key_type;
|
||||
using MappedType = typename Map::mapped_type;
|
||||
|
||||
cl.def("__setitem__",
|
||||
[](Map &m, const KeyType &k, const MappedType &v) {
|
||||
auto it = m.find(k);
|
||||
if (it != m.end()) it->second = v;
|
||||
else m.emplace(k, v);
|
||||
}
|
||||
);
|
||||
cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
|
||||
auto it = m.find(k);
|
||||
if (it != m.end()) {
|
||||
it->second = v;
|
||||
} else {
|
||||
m.emplace(k, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Not copy-assignable, but still copy-constructible: we can update the value by erasing and reinserting
|
||||
template<typename Map, typename Class_>
|
||||
void map_assignment(enable_if_t<
|
||||
!is_copy_assignable<typename Map::mapped_type>::value &&
|
||||
is_copy_constructible<typename Map::mapped_type>::value,
|
||||
Class_> &cl) {
|
||||
// Not copy-assignable, but still copy-constructible: we can update the value by erasing and
|
||||
// reinserting
|
||||
template <typename Map, typename Class_>
|
||||
void map_assignment(enable_if_t<!is_copy_assignable<typename Map::mapped_type>::value
|
||||
&& is_copy_constructible<typename Map::mapped_type>::value,
|
||||
Class_> &cl) {
|
||||
using KeyType = typename Map::key_type;
|
||||
using MappedType = typename Map::mapped_type;
|
||||
|
||||
cl.def("__setitem__",
|
||||
[](Map &m, const KeyType &k, const MappedType &v) {
|
||||
// We can't use m[k] = v; because value type might not be default constructable
|
||||
auto r = m.emplace(k, v);
|
||||
if (!r.second) {
|
||||
// value type is not copy assignable so the only way to insert it is to erase it first...
|
||||
m.erase(r.first);
|
||||
m.emplace(k, v);
|
||||
}
|
||||
}
|
||||
);
|
||||
cl.def("__setitem__", [](Map &m, const KeyType &k, const MappedType &v) {
|
||||
// We can't use m[k] = v; because value type might not be default constructable
|
||||
auto r = m.emplace(k, v);
|
||||
if (!r.second) {
|
||||
// value type is not copy assignable so the only way to insert it is to erase it
|
||||
// first...
|
||||
m.erase(r.first);
|
||||
m.emplace(k, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Map, typename Class_>
|
||||
auto map_if_insertion_operator(Class_ &cl, std::string const &name)
|
||||
-> decltype(std::declval<std::ostream &>() << std::declval<typename Map::key_type>()
|
||||
<< std::declval<typename Map::mapped_type>(),
|
||||
void()) {
|
||||
|
||||
template <typename Map, typename Class_> auto map_if_insertion_operator(Class_ &cl, std::string const &name)
|
||||
-> decltype(std::declval<std::ostream&>() << std::declval<typename Map::key_type>() << std::declval<typename Map::mapped_type>(), void()) {
|
||||
|
||||
cl.def("__repr__",
|
||||
[name](Map &m) {
|
||||
cl.def(
|
||||
"__repr__",
|
||||
[name](Map &m) {
|
||||
std::ostringstream s;
|
||||
s << name << '{';
|
||||
bool f = false;
|
||||
for (auto const &kv : m) {
|
||||
if (f)
|
||||
if (f) {
|
||||
s << ", ";
|
||||
}
|
||||
s << kv.first << ": " << kv.second;
|
||||
f = true;
|
||||
}
|
||||
s << '}';
|
||||
return s.str();
|
||||
},
|
||||
"Return the canonical string representation of this map."
|
||||
);
|
||||
"Return the canonical string representation of this map.");
|
||||
}
|
||||
|
||||
template <typename Map>
|
||||
struct keys_view {
|
||||
Map ↦
|
||||
};
|
||||
|
||||
template <typename Map>
|
||||
struct values_view {
|
||||
Map ↦
|
||||
};
|
||||
|
||||
template <typename Map>
|
||||
struct items_view {
|
||||
Map ↦
|
||||
};
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
|
||||
template <typename Map, typename holder_type = std::unique_ptr<Map>, typename... Args>
|
||||
class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&... args) {
|
||||
class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args &&...args) {
|
||||
using KeyType = typename Map::key_type;
|
||||
using MappedType = typename Map::mapped_type;
|
||||
using KeysView = detail::keys_view<Map>;
|
||||
using ValuesView = detail::values_view<Map>;
|
||||
using ItemsView = detail::items_view<Map>;
|
||||
using Class_ = class_<Map, holder_type>;
|
||||
|
||||
// If either type is a non-module-local bound type then make the map binding non-local as well;
|
||||
// otherwise (e.g. both types are either module-local or converting) the map will be
|
||||
// module-local.
|
||||
auto tinfo = detail::get_type_info(typeid(MappedType));
|
||||
auto *tinfo = detail::get_type_info(typeid(MappedType));
|
||||
bool local = !tinfo || tinfo->module_local;
|
||||
if (local) {
|
||||
tinfo = detail::get_type_info(typeid(KeyType));
|
||||
@ -601,60 +673,112 @@ class_<Map, holder_type> bind_map(handle scope, const std::string &name, Args&&.
|
||||
}
|
||||
|
||||
Class_ cl(scope, name.c_str(), pybind11::module_local(local), std::forward<Args>(args)...);
|
||||
class_<KeysView> keys_view(
|
||||
scope, ("KeysView[" + name + "]").c_str(), pybind11::module_local(local));
|
||||
class_<ValuesView> values_view(
|
||||
scope, ("ValuesView[" + name + "]").c_str(), pybind11::module_local(local));
|
||||
class_<ItemsView> items_view(
|
||||
scope, ("ItemsView[" + name + "]").c_str(), pybind11::module_local(local));
|
||||
|
||||
cl.def(init<>());
|
||||
|
||||
// Register stream insertion operator (if possible)
|
||||
detail::map_if_insertion_operator<Map, Class_>(cl, name);
|
||||
|
||||
cl.def("__bool__",
|
||||
cl.def(
|
||||
"__bool__",
|
||||
[](const Map &m) -> bool { return !m.empty(); },
|
||||
"Check whether the map is nonempty"
|
||||
"Check whether the map is nonempty");
|
||||
|
||||
cl.def(
|
||||
"__iter__",
|
||||
[](Map &m) { return make_key_iterator(m.begin(), m.end()); },
|
||||
keep_alive<0, 1>() /* Essential: keep map alive while iterator exists */
|
||||
);
|
||||
|
||||
cl.def("__iter__",
|
||||
[](Map &m) { return make_key_iterator(m.begin(), m.end()); },
|
||||
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||
cl.def(
|
||||
"keys",
|
||||
[](Map &m) { return KeysView{m}; },
|
||||
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
|
||||
);
|
||||
|
||||
cl.def("items",
|
||||
[](Map &m) { return make_iterator(m.begin(), m.end()); },
|
||||
keep_alive<0, 1>() /* Essential: keep list alive while iterator exists */
|
||||
cl.def(
|
||||
"values",
|
||||
[](Map &m) { return ValuesView{m}; },
|
||||
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
|
||||
);
|
||||
|
||||
cl.def("__getitem__",
|
||||
cl.def(
|
||||
"items",
|
||||
[](Map &m) { return ItemsView{m}; },
|
||||
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
|
||||
);
|
||||
|
||||
cl.def(
|
||||
"__getitem__",
|
||||
[](Map &m, const KeyType &k) -> MappedType & {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end())
|
||||
throw key_error();
|
||||
return it->second;
|
||||
if (it == m.end()) {
|
||||
throw key_error();
|
||||
}
|
||||
return it->second;
|
||||
},
|
||||
return_value_policy::reference_internal // ref + keepalive
|
||||
);
|
||||
|
||||
cl.def("__contains__",
|
||||
[](Map &m, const KeyType &k) -> bool {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end())
|
||||
return false;
|
||||
return true;
|
||||
cl.def("__contains__", [](Map &m, const KeyType &k) -> bool {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end()) {
|
||||
return false;
|
||||
}
|
||||
);
|
||||
return true;
|
||||
});
|
||||
// Fallback for when the object is not of the key type
|
||||
cl.def("__contains__", [](Map &, const object &) -> bool { return false; });
|
||||
|
||||
// Assignment provided only if the type is copyable
|
||||
detail::map_assignment<Map, Class_>(cl);
|
||||
|
||||
cl.def("__delitem__",
|
||||
[](Map &m, const KeyType &k) {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end())
|
||||
throw key_error();
|
||||
m.erase(it);
|
||||
}
|
||||
);
|
||||
cl.def("__delitem__", [](Map &m, const KeyType &k) {
|
||||
auto it = m.find(k);
|
||||
if (it == m.end()) {
|
||||
throw key_error();
|
||||
}
|
||||
m.erase(it);
|
||||
});
|
||||
|
||||
cl.def("__len__", &Map::size);
|
||||
|
||||
keys_view.def("__len__", [](KeysView &view) { return view.map.size(); });
|
||||
keys_view.def(
|
||||
"__iter__",
|
||||
[](KeysView &view) { return make_key_iterator(view.map.begin(), view.map.end()); },
|
||||
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
|
||||
);
|
||||
keys_view.def("__contains__", [](KeysView &view, const KeyType &k) -> bool {
|
||||
auto it = view.map.find(k);
|
||||
if (it == view.map.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
// Fallback for when the object is not of the key type
|
||||
keys_view.def("__contains__", [](KeysView &, const object &) -> bool { return false; });
|
||||
|
||||
values_view.def("__len__", [](ValuesView &view) { return view.map.size(); });
|
||||
values_view.def(
|
||||
"__iter__",
|
||||
[](ValuesView &view) { return make_value_iterator(view.map.begin(), view.map.end()); },
|
||||
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
|
||||
);
|
||||
|
||||
items_view.def("__len__", [](ItemsView &view) { return view.map.size(); });
|
||||
items_view.def(
|
||||
"__iter__",
|
||||
[](ItemsView &view) { return make_iterator(view.map.begin(), view.map.end()); },
|
||||
keep_alive<0, 1>() /* Essential: keep view alive while iterator exists */
|
||||
);
|
||||
|
||||
return cl;
|
||||
}
|
||||
|
||||
|
107
3rdparty/pybind11/noxfile.py
vendored
Normal file
107
3rdparty/pybind11/noxfile.py
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
import os
|
||||
|
||||
import nox
|
||||
|
||||
nox.needs_version = ">=2022.1.7"
|
||||
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.session(reuse_venv=True)
|
||||
def lint(session: nox.Session) -> None:
|
||||
"""
|
||||
Lint the codebase (except for clang-format/tidy).
|
||||
"""
|
||||
session.install("pre-commit")
|
||||
session.run("pre-commit", "run", "-a", *session.posargs)
|
||||
|
||||
|
||||
@nox.session(python=PYTHON_VERSIONS)
|
||||
def tests(session: nox.Session) -> None:
|
||||
"""
|
||||
Run the tests (requires a compiler).
|
||||
"""
|
||||
tmpdir = session.create_tmp()
|
||||
session.install("cmake")
|
||||
session.install("-r", "tests/requirements.txt")
|
||||
session.run(
|
||||
"cmake",
|
||||
"-S.",
|
||||
f"-B{tmpdir}",
|
||||
"-DPYBIND11_WERROR=ON",
|
||||
"-DDOWNLOAD_CATCH=ON",
|
||||
"-DDOWNLOAD_EIGEN=ON",
|
||||
*session.posargs,
|
||||
)
|
||||
session.run("cmake", "--build", tmpdir)
|
||||
session.run("cmake", "--build", tmpdir, "--config=Release", "--target", "check")
|
||||
|
||||
|
||||
@nox.session
|
||||
def tests_packaging(session: nox.Session) -> None:
|
||||
"""
|
||||
Run the packaging tests.
|
||||
"""
|
||||
|
||||
session.install("-r", "tests/requirements.txt", "--prefer-binary")
|
||||
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.
|
||||
"""
|
||||
|
||||
session.install("-r", "docs/requirements.txt")
|
||||
session.chdir("docs")
|
||||
|
||||
if "pdf" in session.posargs:
|
||||
session.run("sphinx-build", "-M", "latexpdf", ".", "_build")
|
||||
return
|
||||
|
||||
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")
|
||||
|
||||
|
||||
@nox.session(reuse_venv=True)
|
||||
def make_changelog(session: nox.Session) -> None:
|
||||
"""
|
||||
Inspect the closed issues and make entries for a changelog.
|
||||
"""
|
||||
session.install("ghapi", "rich")
|
||||
session.run("python", "tools/make_changelog.py")
|
||||
|
||||
|
||||
@nox.session(reuse_venv=True)
|
||||
def build(session: nox.Session) -> None:
|
||||
"""
|
||||
Build SDists and wheels.
|
||||
"""
|
||||
|
||||
session.install("build")
|
||||
session.log("Building normal files")
|
||||
session.run("python", "-m", "build", *session.posargs)
|
||||
session.log("Building pybind11-global files (PYBIND11_GLOBAL_SDIST=1)")
|
||||
session.run(
|
||||
"python", "-m", "build", *session.posargs, env={"PYBIND11_GLOBAL_SDIST": "1"}
|
||||
)
|
11
3rdparty/pybind11/pybind11/__init__.py
vendored
11
3rdparty/pybind11/pybind11/__init__.py
vendored
@ -1,12 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
|
||||
from ._version import version_info, __version__
|
||||
from .commands import get_include, get_cmake_dir
|
||||
if sys.version_info < (3, 6):
|
||||
msg = "pybind11 does not support Python < 3.6. 2.9 was the last release supporting Python 2.7 and 3.5."
|
||||
raise ImportError(msg)
|
||||
|
||||
|
||||
from ._version import __version__, version_info
|
||||
from .commands import get_cmake_dir, get_include, get_pkgconfig_dir
|
||||
|
||||
__all__ = (
|
||||
"version_info",
|
||||
"__version__",
|
||||
"get_include",
|
||||
"get_cmake_dir",
|
||||
"get_pkgconfig_dir",
|
||||
)
|
||||
|
18
3rdparty/pybind11/pybind11/__main__.py
vendored
18
3rdparty/pybind11/pybind11/__main__.py
vendored
@ -1,15 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import print_function
|
||||
# pylint: disable=missing-function-docstring
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import sysconfig
|
||||
|
||||
from .commands import get_include, get_cmake_dir
|
||||
from .commands import get_cmake_dir, get_include, get_pkgconfig_dir
|
||||
|
||||
|
||||
def print_includes():
|
||||
# type: () -> None
|
||||
def print_includes() -> None:
|
||||
dirs = [
|
||||
sysconfig.get_path("include"),
|
||||
sysconfig.get_path("platinclude"),
|
||||
@ -25,8 +23,7 @@ def print_includes():
|
||||
print(" ".join("-I" + d for d in unique_dirs))
|
||||
|
||||
|
||||
def main():
|
||||
# type: () -> None
|
||||
def main() -> None:
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
@ -39,6 +36,11 @@ def main():
|
||||
action="store_true",
|
||||
help="Print the CMake module directory, ideal for setting -Dpybind11_ROOT in CMake.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--pkgconfigdir",
|
||||
action="store_true",
|
||||
help="Print the pkgconfig directory, ideal for setting $PKG_CONFIG_PATH.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
if not sys.argv[1:]:
|
||||
parser.print_help()
|
||||
@ -46,6 +48,8 @@ def main():
|
||||
print_includes()
|
||||
if args.cmakedir:
|
||||
print(get_cmake_dir())
|
||||
if args.pkgconfigdir:
|
||||
print(get_pkgconfig_dir())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
6
3rdparty/pybind11/pybind11/_version.py
vendored
6
3rdparty/pybind11/pybind11/_version.py
vendored
@ -1,12 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from typing import Union
|
||||
|
||||
|
||||
def _to_int(s):
|
||||
def _to_int(s: str) -> Union[int, str]:
|
||||
try:
|
||||
return int(s)
|
||||
except ValueError:
|
||||
return s
|
||||
|
||||
|
||||
__version__ = "2.6.1"
|
||||
__version__ = "2.11.0.dev1"
|
||||
version_info = tuple(_to_int(s) for s in __version__.split("."))
|
||||
|
33
3rdparty/pybind11/pybind11/commands.py
vendored
33
3rdparty/pybind11/pybind11/commands.py
vendored
@ -1,22 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
|
||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
def get_include(user=False):
|
||||
# type: (bool) -> str
|
||||
def get_include(user: bool = False) -> str: # pylint: disable=unused-argument
|
||||
"""
|
||||
Return the path to the pybind11 include directory. The historical "user"
|
||||
argument is unused, and may be removed.
|
||||
"""
|
||||
installed_path = os.path.join(DIR, "include")
|
||||
source_path = os.path.join(os.path.dirname(DIR), "include")
|
||||
return installed_path if os.path.exists(installed_path) else source_path
|
||||
|
||||
|
||||
def get_cmake_dir():
|
||||
# type: () -> str
|
||||
def get_cmake_dir() -> str:
|
||||
"""
|
||||
Return the path to the pybind11 CMake module directory.
|
||||
"""
|
||||
cmake_installed_path = os.path.join(DIR, "share", "cmake", "pybind11")
|
||||
if os.path.exists(cmake_installed_path):
|
||||
return cmake_installed_path
|
||||
else:
|
||||
msg = "pybind11 not installed, installation required to access the CMake files"
|
||||
raise ImportError(msg)
|
||||
|
||||
msg = "pybind11 not installed, installation required to access the CMake files"
|
||||
raise ImportError(msg)
|
||||
|
||||
|
||||
def get_pkgconfig_dir() -> str:
|
||||
"""
|
||||
Return the path to the pybind11 pkgconfig directory.
|
||||
"""
|
||||
pkgconfig_installed_path = os.path.join(DIR, "share", "pkgconfig")
|
||||
if os.path.exists(pkgconfig_installed_path):
|
||||
return pkgconfig_installed_path
|
||||
|
||||
msg = "pybind11 not installed, installation required to access the pkgconfig files"
|
||||
raise ImportError(msg)
|
||||
|
278
3rdparty/pybind11/pybind11/setup_helpers.py
vendored
278
3rdparty/pybind11/pybind11/setup_helpers.py
vendored
@ -1,5 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
This module provides helpers for C++11+ projects using pybind11.
|
||||
|
||||
@ -41,26 +39,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import platform
|
||||
import shlex
|
||||
import shutil
|
||||
import sys
|
||||
import sysconfig
|
||||
import tempfile
|
||||
import threading
|
||||
import platform
|
||||
import warnings
|
||||
from functools import lru_cache
|
||||
from pathlib import Path
|
||||
from typing import (
|
||||
Any,
|
||||
Callable,
|
||||
Dict,
|
||||
Iterable,
|
||||
Iterator,
|
||||
List,
|
||||
Optional,
|
||||
Tuple,
|
||||
TypeVar,
|
||||
Union,
|
||||
)
|
||||
|
||||
try:
|
||||
from setuptools.command.build_ext import build_ext as _build_ext
|
||||
from setuptools import Extension as _Extension
|
||||
from setuptools.command.build_ext import build_ext as _build_ext
|
||||
except ImportError:
|
||||
from distutils.command.build_ext import build_ext as _build_ext
|
||||
from distutils.extension import Extension as _Extension
|
||||
|
||||
import distutils.errors
|
||||
import distutils.ccompiler
|
||||
import distutils.errors
|
||||
|
||||
|
||||
WIN = sys.platform.startswith("win32")
|
||||
PY2 = sys.version_info[0] < 3
|
||||
WIN = sys.platform.startswith("win32") and "mingw" not in sysconfig.get_platform()
|
||||
MACOS = sys.platform.startswith("darwin")
|
||||
STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
|
||||
|
||||
@ -72,7 +84,7 @@ STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
|
||||
# directory into your path if it sits beside your setup.py.
|
||||
|
||||
|
||||
class Pybind11Extension(_Extension):
|
||||
class Pybind11Extension(_Extension): # type: ignore[misc]
|
||||
"""
|
||||
Build a C++11+ Extension module with pybind11. This automatically adds the
|
||||
recommended flags when you init the extension and assumes C++ sources - you
|
||||
@ -84,7 +96,7 @@ class Pybind11Extension(_Extension):
|
||||
* ``stdlib=libc++`` on macOS
|
||||
* ``visibility=hidden`` and ``-g0`` on Unix
|
||||
|
||||
Finally, you can set ``cxx_std`` via constructor or afterwords to enable
|
||||
Finally, you can set ``cxx_std`` via constructor or afterwards to enable
|
||||
flags for C++ std, and a few extra helper flags related to the C++ standard
|
||||
level. It is _highly_ recommended you either set this, or use the provided
|
||||
``build_ext``, which will search for the highest supported extension for
|
||||
@ -94,22 +106,18 @@ class Pybind11Extension(_Extension):
|
||||
|
||||
If you want to add pybind11 headers manually, for example for an exact
|
||||
git checkout, then set ``include_pybind11=False``.
|
||||
|
||||
Warning: do not use property-based access to the instance on Python 2 -
|
||||
this is an ugly old-style class due to Distutils.
|
||||
"""
|
||||
|
||||
def _add_cflags(self, *flags):
|
||||
for flag in flags:
|
||||
if flag not in self.extra_compile_args:
|
||||
self.extra_compile_args.append(flag)
|
||||
# flags are prepended, so that they can be further overridden, e.g. by
|
||||
# ``extra_compile_args=["-g"]``.
|
||||
|
||||
def _add_lflags(self, *flags):
|
||||
for flag in flags:
|
||||
if flag not in self.extra_link_args:
|
||||
self.extra_link_args.append(flag)
|
||||
def _add_cflags(self, flags: List[str]) -> None:
|
||||
self.extra_compile_args[:0] = flags
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
def _add_ldflags(self, flags: List[str]) -> None:
|
||||
self.extra_link_args[:0] = flags
|
||||
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
|
||||
self._cxx_level = 0
|
||||
cxx_std = kwargs.pop("cxx_std", 0)
|
||||
@ -119,9 +127,7 @@ class Pybind11Extension(_Extension):
|
||||
|
||||
include_pybind11 = kwargs.pop("include_pybind11", True)
|
||||
|
||||
# Can't use super here because distutils has old-style classes in
|
||||
# Python 2!
|
||||
_Extension.__init__(self, *args, **kwargs)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
# Include the installed package pybind11 headers
|
||||
if include_pybind11:
|
||||
@ -133,33 +139,41 @@ class Pybind11Extension(_Extension):
|
||||
|
||||
if pyinc not in self.include_dirs:
|
||||
self.include_dirs.append(pyinc)
|
||||
except ImportError:
|
||||
except ModuleNotFoundError:
|
||||
pass
|
||||
|
||||
# Have to use the accessor manually to support Python 2 distutils
|
||||
Pybind11Extension.cxx_std.__set__(self, cxx_std)
|
||||
self.cxx_std = cxx_std
|
||||
|
||||
cflags = []
|
||||
ldflags = []
|
||||
if WIN:
|
||||
self._add_cflags("/EHsc", "/bigobj")
|
||||
cflags += ["/EHsc", "/bigobj"]
|
||||
else:
|
||||
self._add_cflags("-fvisibility=hidden", "-g0")
|
||||
cflags += ["-fvisibility=hidden"]
|
||||
env_cflags = os.environ.get("CFLAGS", "")
|
||||
env_cppflags = os.environ.get("CPPFLAGS", "")
|
||||
c_cpp_flags = shlex.split(env_cflags) + shlex.split(env_cppflags)
|
||||
if not any(opt.startswith("-g") for opt in c_cpp_flags):
|
||||
cflags += ["-g0"]
|
||||
if MACOS:
|
||||
self._add_cflags("-stdlib=libc++")
|
||||
self._add_lflags("-stdlib=libc++")
|
||||
cflags += ["-stdlib=libc++"]
|
||||
ldflags += ["-stdlib=libc++"]
|
||||
self._add_cflags(cflags)
|
||||
self._add_ldflags(ldflags)
|
||||
|
||||
@property
|
||||
def cxx_std(self):
|
||||
def cxx_std(self) -> int:
|
||||
"""
|
||||
The CXX standard level. If set, will add the required flags. If left
|
||||
at 0, it will trigger an automatic search when pybind11's build_ext
|
||||
is used. If None, will have no effect. Besides just the flags, this
|
||||
may add a register warning/error fix for Python 2 or macos-min 10.9
|
||||
or 10.14.
|
||||
The CXX standard level. If set, will add the required flags. If left at
|
||||
0, it will trigger an automatic search when pybind11's build_ext is
|
||||
used. If None, will have no effect. Besides just the flags, this may
|
||||
add a macos-min 10.9 or 10.14 flag if MACOSX_DEPLOYMENT_TARGET is
|
||||
unset.
|
||||
"""
|
||||
return self._cxx_level
|
||||
|
||||
@cxx_std.setter
|
||||
def cxx_std(self, level):
|
||||
def cxx_std(self, level: int) -> None:
|
||||
|
||||
if self._cxx_level:
|
||||
warnings.warn("You cannot safely change the cxx_level after setting it!")
|
||||
@ -174,7 +188,8 @@ class Pybind11Extension(_Extension):
|
||||
if not level:
|
||||
return
|
||||
|
||||
self.extra_compile_args.append(STD_TMPL.format(level))
|
||||
cflags = [STD_TMPL.format(level)]
|
||||
ldflags = []
|
||||
|
||||
if MACOS and "MACOSX_DEPLOYMENT_TARGET" not in os.environ:
|
||||
# C++17 requires a higher min version of macOS. An earlier version
|
||||
@ -185,28 +200,20 @@ class Pybind11Extension(_Extension):
|
||||
current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2])
|
||||
desired_macos = (10, 9) if level < 17 else (10, 14)
|
||||
macos_string = ".".join(str(x) for x in min(current_macos, desired_macos))
|
||||
macosx_min = "-mmacosx-version-min=" + macos_string
|
||||
self.extra_compile_args.append(macosx_min)
|
||||
self.extra_link_args.append(macosx_min)
|
||||
macosx_min = f"-mmacosx-version-min={macos_string}"
|
||||
cflags += [macosx_min]
|
||||
ldflags += [macosx_min]
|
||||
|
||||
if PY2:
|
||||
if WIN:
|
||||
# Will be ignored on MSVC 2015, where C++17 is not supported so
|
||||
# this flag is not valid.
|
||||
self.extra_compile_args.append("/wd5033")
|
||||
elif level >= 17:
|
||||
self.extra_compile_args.append("-Wno-register")
|
||||
elif level >= 14:
|
||||
self.extra_compile_args.append("-Wno-deprecated-register")
|
||||
self._add_cflags(cflags)
|
||||
self._add_ldflags(ldflags)
|
||||
|
||||
|
||||
# Just in case someone clever tries to multithread
|
||||
tmp_chdir_lock = threading.Lock()
|
||||
cpp_cache_lock = threading.Lock()
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def tmp_chdir():
|
||||
def tmp_chdir() -> Iterator[str]:
|
||||
"Prepare and enter a temporary directory, cleanup when done"
|
||||
|
||||
# Threadsafe
|
||||
@ -222,7 +229,7 @@ def tmp_chdir():
|
||||
|
||||
|
||||
# cf http://bugs.python.org/issue26689
|
||||
def has_flag(compiler, flag):
|
||||
def has_flag(compiler: Any, flag: str) -> bool:
|
||||
"""
|
||||
Return the flag if a flag name is supported on the
|
||||
specified compiler, otherwise None (can be used as a boolean).
|
||||
@ -230,12 +237,12 @@ def has_flag(compiler, flag):
|
||||
"""
|
||||
|
||||
with tmp_chdir():
|
||||
fname = "flagcheck.cpp"
|
||||
with open(fname, "w") as f:
|
||||
f.write("int main (int argc, char **argv) { return 0; }")
|
||||
fname = Path("flagcheck.cpp")
|
||||
# Don't trigger -Wunused-parameter.
|
||||
fname.write_text("int main (int, char **) { return 0; }", encoding="utf-8")
|
||||
|
||||
try:
|
||||
compiler.compile([fname], extra_postargs=[flag])
|
||||
compiler.compile([str(fname)], extra_postargs=[flag])
|
||||
except distutils.errors.CompileError:
|
||||
return False
|
||||
return True
|
||||
@ -245,7 +252,8 @@ def has_flag(compiler, flag):
|
||||
cpp_flag_cache = None
|
||||
|
||||
|
||||
def auto_cpp_level(compiler):
|
||||
@lru_cache()
|
||||
def auto_cpp_level(compiler: Any) -> Union[str, int]:
|
||||
"""
|
||||
Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows.
|
||||
"""
|
||||
@ -253,48 +261,78 @@ def auto_cpp_level(compiler):
|
||||
if WIN:
|
||||
return "latest"
|
||||
|
||||
global cpp_flag_cache
|
||||
|
||||
# If this has been previously calculated with the same args, return that
|
||||
with cpp_cache_lock:
|
||||
if cpp_flag_cache:
|
||||
return cpp_flag_cache
|
||||
|
||||
levels = [17, 14, 11]
|
||||
|
||||
for level in levels:
|
||||
if has_flag(compiler, STD_TMPL.format(level)):
|
||||
with cpp_cache_lock:
|
||||
cpp_flag_cache = level
|
||||
return level
|
||||
|
||||
msg = "Unsupported compiler -- at least C++11 support is needed!"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
class build_ext(_build_ext): # noqa: N801
|
||||
class build_ext(_build_ext): # type: ignore[misc] # noqa: N801
|
||||
"""
|
||||
Customized build_ext that allows an auto-search for the highest supported
|
||||
C++ level for Pybind11Extension. This is only needed for the auto-search
|
||||
for now, and is completely optional otherwise.
|
||||
"""
|
||||
|
||||
def build_extensions(self):
|
||||
def build_extensions(self) -> None:
|
||||
"""
|
||||
Build extensions, injecting C++ std for Pybind11Extension if needed.
|
||||
"""
|
||||
|
||||
for ext in self.extensions:
|
||||
if hasattr(ext, "_cxx_level") and ext._cxx_level == 0:
|
||||
# Python 2 syntax - old-style distutils class
|
||||
ext.__class__.cxx_std.__set__(ext, auto_cpp_level(self.compiler))
|
||||
ext.cxx_std = auto_cpp_level(self.compiler)
|
||||
|
||||
# Python 2 doesn't allow super here, since distutils uses old-style
|
||||
# classes!
|
||||
_build_ext.build_extensions(self)
|
||||
super().build_extensions()
|
||||
|
||||
|
||||
def naive_recompile(obj, src):
|
||||
def intree_extensions(
|
||||
paths: Iterable[str], package_dir: Optional[Dict[str, str]] = None
|
||||
) -> List[Pybind11Extension]:
|
||||
"""
|
||||
Generate Pybind11Extensions from source files directly located in a Python
|
||||
source tree.
|
||||
|
||||
``package_dir`` behaves as in ``setuptools.setup``. If unset, the Python
|
||||
package root parent is determined as the first parent directory that does
|
||||
not contain an ``__init__.py`` file.
|
||||
"""
|
||||
exts = []
|
||||
|
||||
if package_dir is None:
|
||||
for path in paths:
|
||||
parent, _ = os.path.split(path)
|
||||
while os.path.exists(os.path.join(parent, "__init__.py")):
|
||||
parent, _ = os.path.split(parent)
|
||||
relname, _ = os.path.splitext(os.path.relpath(path, parent))
|
||||
qualified_name = relname.replace(os.path.sep, ".")
|
||||
exts.append(Pybind11Extension(qualified_name, [path]))
|
||||
return exts
|
||||
|
||||
for path in paths:
|
||||
for prefix, parent in package_dir.items():
|
||||
if path.startswith(parent):
|
||||
relname, _ = os.path.splitext(os.path.relpath(path, parent))
|
||||
qualified_name = relname.replace(os.path.sep, ".")
|
||||
if prefix:
|
||||
qualified_name = prefix + "." + qualified_name
|
||||
exts.append(Pybind11Extension(qualified_name, [path]))
|
||||
break
|
||||
else:
|
||||
msg = (
|
||||
f"path {path} is not a child of any of the directories listed "
|
||||
f"in 'package_dir' ({package_dir})"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
return exts
|
||||
|
||||
|
||||
def naive_recompile(obj: str, src: str) -> bool:
|
||||
"""
|
||||
This will recompile only if the source file changes. It does not check
|
||||
header files, so a more advanced function or Ccache is better if you have
|
||||
@ -303,7 +341,7 @@ def naive_recompile(obj, src):
|
||||
return os.stat(obj).st_mtime < os.stat(src).st_mtime
|
||||
|
||||
|
||||
def no_recompile(obg, src):
|
||||
def no_recompile(obg: str, src: str) -> bool: # pylint: disable=unused-argument
|
||||
"""
|
||||
This is the safest but slowest choice (and is the default) - will always
|
||||
recompile sources.
|
||||
@ -311,15 +349,33 @@ def no_recompile(obg, src):
|
||||
return True
|
||||
|
||||
|
||||
S = TypeVar("S", bound="ParallelCompile")
|
||||
|
||||
CCompilerMethod = Callable[
|
||||
[
|
||||
distutils.ccompiler.CCompiler,
|
||||
List[str],
|
||||
Optional[str],
|
||||
Optional[Union[Tuple[str], Tuple[str, Optional[str]]]],
|
||||
Optional[List[str]],
|
||||
bool,
|
||||
Optional[List[str]],
|
||||
Optional[List[str]],
|
||||
Optional[List[str]],
|
||||
],
|
||||
List[str],
|
||||
]
|
||||
|
||||
|
||||
# Optional parallel compile utility
|
||||
# inspired by: http://stackoverflow.com/questions/11013851/speeding-up-build-process-with-distutils
|
||||
# and: https://github.com/tbenthompson/cppimport/blob/stable/cppimport/build_module.py
|
||||
# and NumPy's parallel distutils module:
|
||||
# https://github.com/numpy/numpy/blob/master/numpy/distutils/ccompiler.py
|
||||
class ParallelCompile(object):
|
||||
class ParallelCompile:
|
||||
"""
|
||||
Make a parallel compile function. Inspired by
|
||||
numpy.distutils.ccompiler.CCompiler_compile and cppimport.
|
||||
numpy.distutils.ccompiler.CCompiler.compile and cppimport.
|
||||
|
||||
This takes several arguments that allow you to customize the compile
|
||||
function created:
|
||||
@ -354,35 +410,41 @@ class ParallelCompile(object):
|
||||
|
||||
__slots__ = ("envvar", "default", "max", "_old", "needs_recompile")
|
||||
|
||||
def __init__(self, envvar=None, default=0, max=0, needs_recompile=no_recompile):
|
||||
def __init__(
|
||||
self,
|
||||
envvar: Optional[str] = None,
|
||||
default: int = 0,
|
||||
max: int = 0, # pylint: disable=redefined-builtin
|
||||
needs_recompile: Callable[[str, str], bool] = no_recompile,
|
||||
) -> None:
|
||||
self.envvar = envvar
|
||||
self.default = default
|
||||
self.max = max
|
||||
self.needs_recompile = needs_recompile
|
||||
self._old = []
|
||||
self._old: List[CCompilerMethod] = []
|
||||
|
||||
def function(self):
|
||||
def function(self) -> CCompilerMethod:
|
||||
"""
|
||||
Builds a function object usable as distutils.ccompiler.CCompiler.compile.
|
||||
"""
|
||||
|
||||
def compile_function(
|
||||
compiler,
|
||||
sources,
|
||||
output_dir=None,
|
||||
macros=None,
|
||||
include_dirs=None,
|
||||
debug=0,
|
||||
extra_preargs=None,
|
||||
extra_postargs=None,
|
||||
depends=None,
|
||||
):
|
||||
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,
|
||||
debug: bool = False,
|
||||
extra_preargs: Optional[List[str]] = None,
|
||||
extra_postargs: Optional[List[str]] = None,
|
||||
depends: Optional[List[str]] = None,
|
||||
) -> Any:
|
||||
|
||||
# These lines are directly from distutils.ccompiler.CCompiler
|
||||
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile(
|
||||
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile( # type: ignore[attr-defined]
|
||||
output_dir, macros, include_dirs, sources, depends, extra_postargs
|
||||
)
|
||||
cc_args = compiler._get_cc_args(pp_opts, debug, extra_preargs)
|
||||
cc_args = compiler._get_cc_args(pp_opts, debug, extra_preargs) # type: ignore[attr-defined]
|
||||
|
||||
# The number of threads; start with default.
|
||||
threads = self.default
|
||||
@ -391,17 +453,19 @@ class ParallelCompile(object):
|
||||
if self.envvar is not None:
|
||||
threads = int(os.environ.get(self.envvar, self.default))
|
||||
|
||||
def _single_compile(obj):
|
||||
def _single_compile(obj: Any) -> None:
|
||||
try:
|
||||
src, ext = build[obj]
|
||||
except KeyError:
|
||||
return
|
||||
|
||||
if not os.path.exists(obj) or self.needs_recompile(obj, src):
|
||||
compiler._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
|
||||
compiler._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) # type: ignore[attr-defined]
|
||||
|
||||
try:
|
||||
import multiprocessing
|
||||
# Importing .synchronize checks for platforms that have some multiprocessing
|
||||
# capabilities but lack semaphores, such as AWS Lambda and Android Termux.
|
||||
import multiprocessing.synchronize
|
||||
from multiprocessing.pool import ThreadPool
|
||||
except ImportError:
|
||||
threads = 1
|
||||
@ -414,8 +478,9 @@ class ParallelCompile(object):
|
||||
threads = 1
|
||||
|
||||
if threads > 1:
|
||||
for _ in ThreadPool(threads).imap_unordered(_single_compile, objects):
|
||||
pass
|
||||
with ThreadPool(threads) as pool:
|
||||
for _ in pool.imap_unordered(_single_compile, objects):
|
||||
pass
|
||||
else:
|
||||
for ob in objects:
|
||||
_single_compile(ob)
|
||||
@ -424,13 +489,16 @@ class ParallelCompile(object):
|
||||
|
||||
return compile_function
|
||||
|
||||
def install(self):
|
||||
distutils.ccompiler.CCompiler.compile = self.function()
|
||||
def install(self: S) -> S:
|
||||
"""
|
||||
Installs the compile function into distutils.ccompiler.CCompiler.compile.
|
||||
"""
|
||||
distutils.ccompiler.CCompiler.compile = self.function() # type: ignore[assignment]
|
||||
return self
|
||||
|
||||
def __enter__(self):
|
||||
def __enter__(self: S) -> S:
|
||||
self._old.append(distutils.ccompiler.CCompiler.compile)
|
||||
return self.install()
|
||||
|
||||
def __exit__(self, *args):
|
||||
distutils.ccompiler.CCompiler.compile = self._old.pop()
|
||||
def __exit__(self, *args: Any) -> None:
|
||||
distutils.ccompiler.CCompiler.compile = self._old.pop() # type: ignore[assignment]
|
||||
|
60
3rdparty/pybind11/pyproject.toml
vendored
60
3rdparty/pybind11/pyproject.toml
vendored
@ -1,3 +1,61 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=42", "wheel", "cmake>=3.18", "ninja"]
|
||||
requires = ["setuptools>=42", "cmake>=3.18", "ninja"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.check-manifest]
|
||||
ignore = [
|
||||
"tests/**",
|
||||
"docs/**",
|
||||
"tools/**",
|
||||
"include/**",
|
||||
".*",
|
||||
"pybind11/include/**",
|
||||
"pybind11/share/**",
|
||||
"CMakeLists.txt",
|
||||
"noxfile.py",
|
||||
]
|
||||
|
||||
[tool.isort]
|
||||
# Needs the compiled .so modules and env.py from tests
|
||||
known_first_party = "env,pybind11_cross_module_tests,pybind11_tests,"
|
||||
# For black compatibility
|
||||
profile = "black"
|
||||
|
||||
[tool.mypy]
|
||||
files = ["pybind11"]
|
||||
python_version = "3.6"
|
||||
strict = true
|
||||
show_error_codes = true
|
||||
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
|
||||
warn_unreachable = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = ["ghapi.*", "setuptools.*"]
|
||||
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"
|
||||
reports.output-format = "colorized"
|
||||
messages_control.disable = [
|
||||
"design",
|
||||
"fixme",
|
||||
"imports",
|
||||
"line-too-long",
|
||||
"imports",
|
||||
"invalid-name",
|
||||
"protected-access",
|
||||
"missing-module-docstring",
|
||||
]
|
||||
|
49
3rdparty/pybind11/setup.cfg
vendored
49
3rdparty/pybind11/setup.cfg
vendored
@ -13,13 +13,13 @@ classifiers =
|
||||
Topic :: Software Development :: Libraries :: Python Modules
|
||||
Topic :: Utilities
|
||||
Programming Language :: C++
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.5
|
||||
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
|
||||
License :: OSI Approved :: BSD License
|
||||
Programming Language :: Python :: Implementation :: PyPy
|
||||
Programming Language :: Python :: Implementation :: CPython
|
||||
@ -30,42 +30,21 @@ keywords =
|
||||
C++11
|
||||
Python bindings
|
||||
|
||||
project_urls =
|
||||
Documentation = https://pybind11.readthedocs.io/
|
||||
Bug Tracker = https://github.com/pybind/pybind11/issues
|
||||
Discussions = https://github.com/pybind/pybind11/discussions
|
||||
Changelog = https://pybind11.readthedocs.io/en/latest/changelog.html
|
||||
Chat = https://gitter.im/pybind/Lobby
|
||||
|
||||
[options]
|
||||
python_requires = >=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4
|
||||
python_requires = >=3.6
|
||||
zip_safe = False
|
||||
|
||||
[bdist_wheel]
|
||||
universal=1
|
||||
|
||||
[check-manifest]
|
||||
ignore =
|
||||
tests/**
|
||||
docs/**
|
||||
tools/**
|
||||
include/**
|
||||
.appveyor.yml
|
||||
.cmake-format.yaml
|
||||
.gitmodules
|
||||
.pre-commit-config.yaml
|
||||
.readthedocs.yml
|
||||
.clang-tidy
|
||||
pybind11/include/**
|
||||
pybind11/share/**
|
||||
CMakeLists.txt
|
||||
|
||||
|
||||
[flake8]
|
||||
max-line-length = 99
|
||||
max-line-length = 120
|
||||
show_source = True
|
||||
exclude = .git, __pycache__, build, dist, docs, tools, venv
|
||||
ignore =
|
||||
# required for pretty matrix formatting: multiple spaces after `,` and `[`
|
||||
E201, E241, W504,
|
||||
# camelcase 'cPickle' imported as lowercase 'pickle'
|
||||
N813
|
||||
# Black conflict
|
||||
W503, E203
|
||||
|
||||
[mypy]
|
||||
files = pybind11
|
||||
strict = True
|
||||
extend-ignore = E203, E722, B903, B950
|
||||
extend-select = B9
|
||||
|
121
3rdparty/pybind11/setup.py
vendored
121
3rdparty/pybind11/setup.py
vendored
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Setup script for PyPI; use CMakeFile.txt to build extension modules
|
||||
|
||||
@ -10,87 +9,110 @@ import shutil
|
||||
import string
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from tempfile import TemporaryDirectory
|
||||
from typing import Dict, Iterator, List, Union
|
||||
|
||||
import setuptools.command.sdist
|
||||
|
||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
DIR = Path(__file__).parent.absolute()
|
||||
VERSION_REGEX = re.compile(
|
||||
r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
|
||||
)
|
||||
VERSION_FILE = Path("pybind11/_version.py")
|
||||
COMMON_FILE = Path("include/pybind11/detail/common.h")
|
||||
|
||||
|
||||
def build_expected_version_hex(matches: Dict[str, str]) -> str:
|
||||
patch_level_serial = matches["PATCH"]
|
||||
serial = None
|
||||
major = int(matches["MAJOR"])
|
||||
minor = int(matches["MINOR"])
|
||||
flds = patch_level_serial.split(".")
|
||||
if flds:
|
||||
patch = int(flds[0])
|
||||
if len(flds) == 1:
|
||||
level = "0"
|
||||
serial = 0
|
||||
elif len(flds) == 2:
|
||||
level_serial = flds[1]
|
||||
for level in ("a", "b", "c", "dev"):
|
||||
if level_serial.startswith(level):
|
||||
serial = int(level_serial[len(level) :])
|
||||
break
|
||||
if serial is None:
|
||||
msg = f'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"'
|
||||
raise RuntimeError(msg)
|
||||
version_hex_str = f"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}"
|
||||
return f"0x{version_hex_str.upper()}"
|
||||
|
||||
|
||||
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
|
||||
# files, and the sys.prefix files (CMake and headers).
|
||||
|
||||
global_sdist = os.environ.get("PYBIND11_GLOBAL_SDIST", False)
|
||||
|
||||
setup_py = "tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
|
||||
setup_py = Path(
|
||||
"tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
|
||||
)
|
||||
extra_cmd = 'cmdclass["sdist"] = SDist\n'
|
||||
|
||||
to_src = (
|
||||
("pyproject.toml", "tools/pyproject.toml"),
|
||||
("setup.py", setup_py),
|
||||
(Path("pyproject.toml"), Path("tools/pyproject.toml")),
|
||||
(Path("setup.py"), setup_py),
|
||||
)
|
||||
|
||||
|
||||
# Read the listed version
|
||||
with open("pybind11/_version.py") as f:
|
||||
code = compile(f.read(), "pybind11/_version.py", "exec")
|
||||
loc = {}
|
||||
loc: Dict[str, str] = {}
|
||||
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
|
||||
exec(code, loc)
|
||||
version = loc["__version__"]
|
||||
|
||||
# Verify that the version matches the one in C++
|
||||
with open("include/pybind11/detail/common.h") as f:
|
||||
matches = dict(VERSION_REGEX.findall(f.read()))
|
||||
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
|
||||
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
|
||||
if version != cpp_version:
|
||||
msg = "Python version {} does not match C++ version {}!".format(
|
||||
version, cpp_version
|
||||
)
|
||||
msg = f"Python version {version} does not match C++ version {cpp_version}!"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
version_hex = matches.get("HEX", "MISSING")
|
||||
exp_version_hex = build_expected_version_hex(matches)
|
||||
if version_hex != exp_version_hex:
|
||||
msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
def get_and_replace(filename, binary=False, **opts):
|
||||
with open(filename, "rb" if binary else "r") as f:
|
||||
contents = f.read()
|
||||
# Replacement has to be done on text in Python 3 (both work in Python 2)
|
||||
# TODO: use literals & overload (typing extensions or Python 3.8)
|
||||
def get_and_replace(
|
||||
filename: Path, binary: bool = False, **opts: str
|
||||
) -> Union[bytes, str]:
|
||||
if binary:
|
||||
contents = filename.read_bytes()
|
||||
return string.Template(contents.decode()).substitute(opts).encode()
|
||||
else:
|
||||
return string.Template(contents).substitute(opts)
|
||||
|
||||
return string.Template(filename.read_text()).substitute(opts)
|
||||
|
||||
|
||||
# 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, files):
|
||||
setuptools.command.sdist.sdist.make_release_tree(self, base_dir, files)
|
||||
class SDist(setuptools.command.sdist.sdist): # type: ignore[misc]
|
||||
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:
|
||||
txt = get_and_replace(src, binary=True, version=version, extra_cmd="")
|
||||
|
||||
dest = os.path.join(base_dir, to)
|
||||
dest = Path(base_dir) / to
|
||||
|
||||
# This is normally linked, so unlink before writing!
|
||||
os.unlink(dest)
|
||||
with open(dest, "wb") as f:
|
||||
f.write(txt)
|
||||
|
||||
|
||||
# Backport from Python 3
|
||||
@contextlib.contextmanager
|
||||
def TemporaryDirectory(): # noqa: N802
|
||||
"Prepare a temporary directory, cleanup when done"
|
||||
try:
|
||||
tmpdir = tempfile.mkdtemp()
|
||||
yield tmpdir
|
||||
finally:
|
||||
shutil.rmtree(tmpdir)
|
||||
dest.unlink()
|
||||
dest.write_bytes(txt) # type: ignore[arg-type]
|
||||
|
||||
|
||||
# Remove the CMake install directory when done
|
||||
@contextlib.contextmanager
|
||||
def remove_output(*sources):
|
||||
def remove_output(*sources: str) -> Iterator[None]:
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
@ -105,10 +127,23 @@ with remove_output("pybind11/include", "pybind11/share"):
|
||||
"-DCMAKE_INSTALL_PREFIX=pybind11",
|
||||
"-DBUILD_TESTING=OFF",
|
||||
"-DPYBIND11_NOPYTHON=ON",
|
||||
"-Dprefix_for_pc_file=${pcfiledir}/../../",
|
||||
]
|
||||
cmake_opts = dict(cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
|
||||
subprocess.check_call(cmd, **cmake_opts)
|
||||
subprocess.check_call(["cmake", "--install", tmpdir], **cmake_opts)
|
||||
if "CMAKE_ARGS" in os.environ:
|
||||
fcommand = [
|
||||
c
|
||||
for c in os.environ["CMAKE_ARGS"].split()
|
||||
if "DCMAKE_INSTALL_PREFIX" not in c
|
||||
]
|
||||
cmd += fcommand
|
||||
subprocess.run(cmd, check=True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
|
||||
subprocess.run(
|
||||
["cmake", "--install", tmpdir],
|
||||
check=True,
|
||||
cwd=DIR,
|
||||
stdout=sys.stdout,
|
||||
stderr=sys.stderr,
|
||||
)
|
||||
|
||||
txt = get_and_replace(setup_py, version=version, extra_cmd=extra_cmd)
|
||||
code = compile(txt, setup_py, "exec")
|
||||
|
337
3rdparty/pybind11/tests/CMakeLists.txt
vendored
337
3rdparty/pybind11/tests/CMakeLists.txt
vendored
@ -10,27 +10,34 @@ cmake_minimum_required(VERSION 3.4)
|
||||
# The `cmake_minimum_required(VERSION 3.4...3.18)` 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.18)
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.21)
|
||||
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
|
||||
else()
|
||||
cmake_policy(VERSION 3.18)
|
||||
cmake_policy(VERSION 3.21)
|
||||
endif()
|
||||
|
||||
# Only needed for CMake < 3.5 support
|
||||
include(CMakeParseArguments)
|
||||
|
||||
# Filter out items; print an optional message if any items filtered
|
||||
# Filter out items; print an optional message if any items filtered. This ignores extensions.
|
||||
#
|
||||
# Usage:
|
||||
# pybind11_filter_tests(LISTNAME file1.cpp file2.cpp ... MESSAGE "")
|
||||
#
|
||||
macro(PYBIND11_FILTER_TESTS LISTNAME)
|
||||
macro(pybind11_filter_tests LISTNAME)
|
||||
cmake_parse_arguments(ARG "" "MESSAGE" "" ${ARGN})
|
||||
set(PYBIND11_FILTER_TESTS_FOUND OFF)
|
||||
# Make a list of the test without any extensions, for easier filtering.
|
||||
set(_TMP_ACTUAL_LIST "${${LISTNAME}};") # enforce ';' at the end to allow matching last item.
|
||||
string(REGEX REPLACE "\\.[^.;]*;" ";" LIST_WITHOUT_EXTENSIONS "${_TMP_ACTUAL_LIST}")
|
||||
foreach(filename IN LISTS ARG_UNPARSED_ARGUMENTS)
|
||||
list(FIND ${LISTNAME} ${filename} _FILE_FOUND)
|
||||
string(REGEX REPLACE "\\.[^.]*$" "" filename_no_ext ${filename})
|
||||
# Search in the list without extensions.
|
||||
list(FIND LIST_WITHOUT_EXTENSIONS ${filename_no_ext} _FILE_FOUND)
|
||||
if(_FILE_FOUND GREATER -1)
|
||||
list(REMOVE_AT ${LISTNAME} ${_FILE_FOUND})
|
||||
list(REMOVE_AT ${LISTNAME} ${_FILE_FOUND}) # And remove from the list with extensions.
|
||||
list(REMOVE_AT LIST_WITHOUT_EXTENSIONS ${_FILE_FOUND}
|
||||
)# And our search list, to ensure it is in sync.
|
||||
set(PYBIND11_FILTER_TESTS_FOUND ON)
|
||||
endif()
|
||||
endforeach()
|
||||
@ -39,6 +46,26 @@ macro(PYBIND11_FILTER_TESTS LISTNAME)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(possibly_uninitialized)
|
||||
foreach(VARNAME ${ARGN})
|
||||
if(NOT DEFINED "${VARNAME}")
|
||||
set("${VARNAME}" "")
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Function to add additional targets if any of the provided tests are found.
|
||||
# Needles; Specifies the test names to look for.
|
||||
# Additions; Specifies the additional test targets to add when any of the needles are found.
|
||||
macro(tests_extra_targets needles additions)
|
||||
# Add the index for this relation to the index extra targets map.
|
||||
list(LENGTH PYBIND11_TEST_EXTRA_TARGETS PYBIND11_TEST_EXTRA_TARGETS_LEN)
|
||||
list(APPEND PYBIND11_TEST_EXTRA_TARGETS ${PYBIND11_TEST_EXTRA_TARGETS_LEN})
|
||||
# Add the test names to look for, and the associated test target additions.
|
||||
set(PYBIND11_TEST_EXTRA_TARGETS_NEEDLES_${PYBIND11_TEST_EXTRA_TARGETS_LEN} ${needles})
|
||||
set(PYBIND11_TEST_EXTRA_TARGETS_ADDITION_${PYBIND11_TEST_EXTRA_TARGETS_LEN} ${additions})
|
||||
endmacro()
|
||||
|
||||
# New Python support
|
||||
if(DEFINED Python_EXECUTABLE)
|
||||
set(PYTHON_EXECUTABLE "${Python_EXECUTABLE}")
|
||||
@ -67,7 +94,7 @@ if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
find_package(pybind11 REQUIRED CONFIG)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting tests build type to MinSizeRel as none was specified")
|
||||
set(CMAKE_BUILD_TYPE
|
||||
MinSizeRel
|
||||
@ -84,52 +111,67 @@ if(PYBIND11_CUDA_TESTS)
|
||||
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
|
||||
endif()
|
||||
|
||||
# Full set of test files (you can override these; see below)
|
||||
# Full set of test files (you can override these; see below, overrides ignore extension)
|
||||
# Any test that has no extension is both .py and .cpp, so 'foo' will add 'foo.cpp' and 'foo.py'.
|
||||
# Any test that has an extension is exclusively that and handled as such.
|
||||
set(PYBIND11_TEST_FILES
|
||||
test_async.cpp
|
||||
test_buffers.cpp
|
||||
test_builtin_casters.cpp
|
||||
test_call_policies.cpp
|
||||
test_callbacks.cpp
|
||||
test_chrono.cpp
|
||||
test_class.cpp
|
||||
test_constants_and_functions.cpp
|
||||
test_copy_move.cpp
|
||||
test_custom_type_casters.cpp
|
||||
test_docstring_options.cpp
|
||||
test_eigen.cpp
|
||||
test_enum.cpp
|
||||
test_eval.cpp
|
||||
test_exceptions.cpp
|
||||
test_factory_constructors.cpp
|
||||
test_gil_scoped.cpp
|
||||
test_iostream.cpp
|
||||
test_kwargs_and_defaults.cpp
|
||||
test_local_bindings.cpp
|
||||
test_methods_and_attributes.cpp
|
||||
test_modules.cpp
|
||||
test_multiple_inheritance.cpp
|
||||
test_numpy_array.cpp
|
||||
test_numpy_dtypes.cpp
|
||||
test_numpy_vectorize.cpp
|
||||
test_opaque_types.cpp
|
||||
test_operator_overloading.cpp
|
||||
test_pickling.cpp
|
||||
test_pytypes.cpp
|
||||
test_sequences_and_iterators.cpp
|
||||
test_smart_ptr.cpp
|
||||
test_stl.cpp
|
||||
test_stl_binders.cpp
|
||||
test_tagbased_polymorphic.cpp
|
||||
test_union.cpp
|
||||
test_virtual_functions.cpp)
|
||||
test_async
|
||||
test_buffers
|
||||
test_builtin_casters
|
||||
test_call_policies
|
||||
test_callbacks
|
||||
test_chrono
|
||||
test_class
|
||||
test_const_name
|
||||
test_constants_and_functions
|
||||
test_copy_move
|
||||
test_custom_type_casters
|
||||
test_custom_type_setup
|
||||
test_docstring_options
|
||||
test_eigen
|
||||
test_enum
|
||||
test_eval
|
||||
test_exceptions
|
||||
test_factory_constructors
|
||||
test_gil_scoped
|
||||
test_iostream
|
||||
test_kwargs_and_defaults
|
||||
test_local_bindings
|
||||
test_methods_and_attributes
|
||||
test_modules
|
||||
test_multiple_inheritance
|
||||
test_numpy_array
|
||||
test_numpy_dtypes
|
||||
test_numpy_vectorize
|
||||
test_opaque_types
|
||||
test_operator_overloading
|
||||
test_pickling
|
||||
test_pytypes
|
||||
test_sequences_and_iterators
|
||||
test_smart_ptr
|
||||
test_stl
|
||||
test_stl_binders
|
||||
test_tagbased_polymorphic
|
||||
test_thread
|
||||
test_union
|
||||
test_virtual_functions)
|
||||
|
||||
# Invoking cmake with something like:
|
||||
# cmake -DPYBIND11_TEST_OVERRIDE="test_callbacks.cpp;test_pickling.cpp" ..
|
||||
# lets you override the tests that get compiled and run. You can restore to all tests with:
|
||||
# cmake -DPYBIND11_TEST_OVERRIDE= ..
|
||||
if(PYBIND11_TEST_OVERRIDE)
|
||||
set(PYBIND11_TEST_FILES ${PYBIND11_TEST_OVERRIDE})
|
||||
# Instead of doing a direct override here, we iterate over the overrides without extension and
|
||||
# match them against entries from the PYBIND11_TEST_FILES, anything that not matches goes into the filter list.
|
||||
string(REGEX REPLACE "\\.[^.;]*;" ";" TEST_OVERRIDE_NO_EXT "${PYBIND11_TEST_OVERRIDE};")
|
||||
string(REGEX REPLACE "\\.[^.;]*;" ";" TEST_FILES_NO_EXT "${PYBIND11_TEST_FILES};")
|
||||
# This allows the override to be done with extensions, preserving backwards compatibility.
|
||||
foreach(test_name ${TEST_FILES_NO_EXT})
|
||||
if(NOT ${test_name} IN_LIST TEST_OVERRIDE_NO_EXT
|
||||
)# If not in the whitelist, add to be filtered out.
|
||||
list(APPEND PYBIND11_TEST_FILTER ${test_name})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# You can also filter tests:
|
||||
@ -137,11 +179,6 @@ if(PYBIND11_TEST_FILTER)
|
||||
pybind11_filter_tests(PYBIND11_TEST_FILES ${PYBIND11_TEST_FILTER})
|
||||
endif()
|
||||
|
||||
if(PYTHON_VERSION VERSION_LESS 3.5)
|
||||
pybind11_filter_tests(PYBIND11_TEST_FILES test_async.cpp MESSAGE
|
||||
"Skipping test_async on Python 2")
|
||||
endif()
|
||||
|
||||
# Skip tests for CUDA check:
|
||||
# /pybind11/tests/test_constants_and_functions.cpp(125):
|
||||
# error: incompatible exception specifications
|
||||
@ -151,15 +188,47 @@ if(PYBIND11_CUDA_TESTS)
|
||||
"Skipping test_constants_and_functions due to incompatible exception specifications")
|
||||
endif()
|
||||
|
||||
string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}")
|
||||
# Now that the test filtering is complete, we need to split the list into the test for PYTEST
|
||||
# and the list for the cpp targets.
|
||||
set(PYBIND11_CPPTEST_FILES "")
|
||||
set(PYBIND11_PYTEST_FILES "")
|
||||
|
||||
foreach(test_name ${PYBIND11_TEST_FILES})
|
||||
if(test_name MATCHES "\\.py$") # Ends in .py, purely python test.
|
||||
list(APPEND PYBIND11_PYTEST_FILES ${test_name})
|
||||
elseif(test_name MATCHES "\\.cpp$") # Ends in .cpp, purely cpp test.
|
||||
list(APPEND PYBIND11_CPPTEST_FILES ${test_name})
|
||||
elseif(NOT test_name MATCHES "\\.") # No extension specified, assume both, add extension.
|
||||
list(APPEND PYBIND11_PYTEST_FILES ${test_name}.py)
|
||||
list(APPEND PYBIND11_CPPTEST_FILES ${test_name}.cpp)
|
||||
else()
|
||||
message(WARNING "Unhanded test extension in test: ${test_name}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(PYBIND11_TEST_FILES ${PYBIND11_CPPTEST_FILES})
|
||||
list(SORT PYBIND11_PYTEST_FILES)
|
||||
|
||||
# Contains the set of test files that require pybind11_cross_module_tests to be
|
||||
# built; if none of these are built (i.e. because TEST_OVERRIDE is used and
|
||||
# doesn't include them) the second module doesn't get built.
|
||||
set(PYBIND11_CROSS_MODULE_TESTS test_exceptions.py test_local_bindings.py test_stl.py
|
||||
test_stl_binders.py)
|
||||
tests_extra_targets("test_exceptions.py;test_local_bindings.py;test_stl.py;test_stl_binders.py"
|
||||
"pybind11_cross_module_tests")
|
||||
|
||||
set(PYBIND11_CROSS_MODULE_GIL_TESTS test_gil_scoped.py)
|
||||
# And add additional targets for other tests.
|
||||
tests_extra_targets("test_exceptions.py" "cross_module_interleaved_error_already_set")
|
||||
tests_extra_targets("test_gil_scoped.py" "cross_module_gil_utils")
|
||||
|
||||
set(PYBIND11_EIGEN_REPO
|
||||
"https://gitlab.com/libeigen/eigen.git"
|
||||
CACHE STRING "Eigen repository to use for tests")
|
||||
# Always use a hash for reconfigure speed and security reasons
|
||||
# Include the version number for pretty printing (keep in sync)
|
||||
set(PYBIND11_EIGEN_VERSION_AND_HASH
|
||||
"3.4.0;929bc0e191d0927b1735b9a1ddc0e8b77e3a25ec"
|
||||
CACHE STRING "Eigen version to use for tests, format: VERSION;HASH")
|
||||
|
||||
list(GET PYBIND11_EIGEN_VERSION_AND_HASH 0 PYBIND11_EIGEN_VERSION_STRING)
|
||||
list(GET PYBIND11_EIGEN_VERSION_AND_HASH 1 PYBIND11_EIGEN_VERSION_HASH)
|
||||
|
||||
# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but
|
||||
# keep it in PYBIND11_PYTEST_FILES, so that we get the "eigen is not installed"
|
||||
@ -174,22 +243,26 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
|
||||
message(FATAL_ERROR "CMake 3.11+ required when using DOWNLOAD_EIGEN")
|
||||
endif()
|
||||
|
||||
set(EIGEN3_VERSION_STRING "3.3.8")
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
eigen
|
||||
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
|
||||
GIT_TAG ${EIGEN3_VERSION_STRING})
|
||||
GIT_REPOSITORY "${PYBIND11_EIGEN_REPO}"
|
||||
GIT_TAG "${PYBIND11_EIGEN_VERSION_HASH}")
|
||||
|
||||
FetchContent_GetProperties(eigen)
|
||||
if(NOT eigen_POPULATED)
|
||||
message(STATUS "Downloading Eigen")
|
||||
message(
|
||||
STATUS
|
||||
"Downloading Eigen ${PYBIND11_EIGEN_VERSION_STRING} (${PYBIND11_EIGEN_VERSION_HASH}) from ${PYBIND11_EIGEN_REPO}"
|
||||
)
|
||||
FetchContent_Populate(eigen)
|
||||
endif()
|
||||
|
||||
set(EIGEN3_INCLUDE_DIR ${eigen_SOURCE_DIR})
|
||||
set(EIGEN3_FOUND TRUE)
|
||||
# When getting locally, the version is not visible from a superprojet,
|
||||
# so just force it.
|
||||
set(EIGEN3_VERSION "${PYBIND11_EIGEN_VERSION_STRING}")
|
||||
|
||||
else()
|
||||
find_package(Eigen3 3.2.7 QUIET CONFIG)
|
||||
@ -217,7 +290,8 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
|
||||
message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}")
|
||||
else()
|
||||
list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_EIGEN_I})
|
||||
message(STATUS "Building tests WITHOUT Eigen, use -DDOWNLOAD_EIGEN on CMake 3.11+ to download")
|
||||
message(
|
||||
STATUS "Building tests WITHOUT Eigen, use -DDOWNLOAD_EIGEN=ON on CMake 3.11+ to download")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -238,10 +312,47 @@ if(Boost_FOUND)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check if we need to add -lstdc++fs or -lc++fs or nothing
|
||||
if(DEFINED CMAKE_CXX_STANDARD AND CMAKE_CXX_STANDARD LESS 17)
|
||||
set(STD_FS_NO_LIB_NEEDED TRUE)
|
||||
elseif(MSVC)
|
||||
set(STD_FS_NO_LIB_NEEDED TRUE)
|
||||
else()
|
||||
file(
|
||||
WRITE ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
"#include <filesystem>\nint main(int argc, char ** argv) {\n std::filesystem::path p(argv[0]);\n return p.string().length();\n}"
|
||||
)
|
||||
try_compile(
|
||||
STD_FS_NO_LIB_NEEDED ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
COMPILE_DEFINITIONS -std=c++17)
|
||||
try_compile(
|
||||
STD_FS_NEEDS_STDCXXFS ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
COMPILE_DEFINITIONS -std=c++17
|
||||
LINK_LIBRARIES stdc++fs)
|
||||
try_compile(
|
||||
STD_FS_NEEDS_CXXFS ${CMAKE_CURRENT_BINARY_DIR}
|
||||
SOURCES ${CMAKE_CURRENT_BINARY_DIR}/main.cpp
|
||||
COMPILE_DEFINITIONS -std=c++17
|
||||
LINK_LIBRARIES c++fs)
|
||||
endif()
|
||||
|
||||
if(${STD_FS_NEEDS_STDCXXFS})
|
||||
set(STD_FS_LIB stdc++fs)
|
||||
elseif(${STD_FS_NEEDS_CXXFS})
|
||||
set(STD_FS_LIB c++fs)
|
||||
elseif(${STD_FS_NO_LIB_NEEDED})
|
||||
set(STD_FS_LIB "")
|
||||
else()
|
||||
message(WARNING "Unknown C++17 compiler - not passing -lstdc++fs")
|
||||
set(STD_FS_LIB "")
|
||||
endif()
|
||||
|
||||
# Compile with compiler warnings turned on
|
||||
function(pybind11_enable_warnings target_name)
|
||||
if(MSVC)
|
||||
target_compile_options(${target_name} PRIVATE /W4)
|
||||
target_compile_options(${target_name} PRIVATE /W4 /wd4189)
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Intel|Clang)" AND NOT PYBIND11_CUDA_TESTS)
|
||||
target_compile_options(
|
||||
${target_name}
|
||||
@ -259,40 +370,35 @@ function(pybind11_enable_warnings target_name)
|
||||
target_compile_options(${target_name} PRIVATE /WX)
|
||||
elseif(PYBIND11_CUDA_TESTS)
|
||||
target_compile_options(${target_name} PRIVATE "SHELL:-Werror all-warnings")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Intel|Clang)")
|
||||
elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang|IntelLLVM)")
|
||||
target_compile_options(${target_name} PRIVATE -Werror)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Needs to be readded since the ordering requires these to be after the ones above
|
||||
if(CMAKE_CXX_STANDARD
|
||||
AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"
|
||||
AND PYTHON_VERSION VERSION_LESS 3.0)
|
||||
if(CMAKE_CXX_STANDARD LESS 17)
|
||||
target_compile_options(${target_name} PUBLIC -Wno-deprecated-register)
|
||||
else()
|
||||
target_compile_options(${target_name} PUBLIC -Wno-register)
|
||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||
if(CMAKE_CXX_STANDARD EQUAL 17) # See PR #3570
|
||||
target_compile_options(${target_name} PRIVATE -Wno-conversion)
|
||||
endif()
|
||||
target_compile_options(
|
||||
${target_name}
|
||||
PRIVATE
|
||||
-Werror-all
|
||||
# "Inlining inhibited by limit max-size", "Inlining inhibited by limit max-total-size"
|
||||
-diag-disable 11074,11076)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
set(test_targets pybind11_tests)
|
||||
|
||||
# Build pybind11_cross_module_tests if any test_whatever.py are being built that require it
|
||||
foreach(t ${PYBIND11_CROSS_MODULE_TESTS})
|
||||
list(FIND PYBIND11_PYTEST_FILES ${t} i)
|
||||
if(i GREATER -1)
|
||||
list(APPEND test_targets pybind11_cross_module_tests)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
foreach(t ${PYBIND11_CROSS_MODULE_GIL_TESTS})
|
||||
list(FIND PYBIND11_PYTEST_FILES ${t} i)
|
||||
if(i GREATER -1)
|
||||
list(APPEND test_targets cross_module_gil_utils)
|
||||
break()
|
||||
endif()
|
||||
# Check if any tests need extra targets by iterating through the mappings registered.
|
||||
foreach(i ${PYBIND11_TEST_EXTRA_TARGETS})
|
||||
foreach(needle ${PYBIND11_TEST_EXTRA_TARGETS_NEEDLES_${i}})
|
||||
if(needle IN_LIST PYBIND11_PYTEST_FILES)
|
||||
# Add all the additional targets to the test list. List join in newer cmake.
|
||||
foreach(extra_target ${PYBIND11_TEST_EXTRA_TARGETS_ADDITION_${i}})
|
||||
list(APPEND test_targets ${extra_target})
|
||||
endforeach()
|
||||
break() # Breaks out of the needle search, continues with the next mapping.
|
||||
endif()
|
||||
endforeach()
|
||||
endforeach()
|
||||
|
||||
# Support CUDA testing by forcing the target file to compile with NVCC
|
||||
@ -341,18 +447,31 @@ foreach(target ${test_targets})
|
||||
target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_BOOST)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${target} PRIVATE ${STD_FS_LIB})
|
||||
|
||||
# Always write the output file directly into the 'tests' directory (even on MSVC)
|
||||
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
|
||||
set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
foreach(config ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER ${config} config)
|
||||
set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endforeach()
|
||||
|
||||
if(DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||
foreach(config ${CMAKE_CONFIGURATION_TYPES})
|
||||
string(TOUPPER ${config} config)
|
||||
set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config}
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endforeach()
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Provide nice organisation in IDEs
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.8)
|
||||
source_group(
|
||||
TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include"
|
||||
PREFIX "Header Files"
|
||||
FILES ${PYBIND11_HEADERS})
|
||||
endif()
|
||||
|
||||
# Make sure pytest is found or produce a warning
|
||||
pybind11_find_import(pytest VERSION 3.1)
|
||||
|
||||
@ -370,12 +489,17 @@ endif()
|
||||
string(REPLACE "test_" "${CMAKE_CURRENT_SOURCE_DIR}/test_" PYBIND11_ABS_PYTEST_FILES
|
||||
"${PYBIND11_PYTEST_FILES}")
|
||||
|
||||
set(PYBIND11_TEST_PREFIX_COMMAND
|
||||
""
|
||||
CACHE STRING "Put this before pytest, use for checkers and such")
|
||||
|
||||
# A single command to compile and run the tests
|
||||
add_custom_target(
|
||||
pytest
|
||||
COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_ABS_PYTEST_FILES}
|
||||
COMMAND ${PYBIND11_TEST_PREFIX_COMMAND} ${PYTHON_EXECUTABLE} -m pytest
|
||||
${PYBIND11_ABS_PYTEST_FILES}
|
||||
DEPENDS ${test_targets}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
USES_TERMINAL)
|
||||
|
||||
if(PYBIND11_TEST_OVERRIDE)
|
||||
@ -386,6 +510,27 @@ if(PYBIND11_TEST_OVERRIDE)
|
||||
"Note: not all tests run: -DPYBIND11_TEST_OVERRIDE is in effect")
|
||||
endif()
|
||||
|
||||
# cmake-format: off
|
||||
add_custom_target(
|
||||
memcheck
|
||||
COMMAND
|
||||
PYTHONMALLOC=malloc
|
||||
valgrind
|
||||
--leak-check=full
|
||||
--show-leak-kinds=definite,indirect
|
||||
--errors-for-leak-kinds=definite,indirect
|
||||
--error-exitcode=1
|
||||
--read-var-info=yes
|
||||
--track-origins=yes
|
||||
--suppressions="${CMAKE_CURRENT_SOURCE_DIR}/valgrind-python.supp"
|
||||
--suppressions="${CMAKE_CURRENT_SOURCE_DIR}/valgrind-numpy-scipy.supp"
|
||||
--gen-suppressions=all
|
||||
${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_ABS_PYTEST_FILES}
|
||||
DEPENDS ${test_targets}
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
|
||||
USES_TERMINAL)
|
||||
# cmake-format: on
|
||||
|
||||
# Add a check target to run all the tests, starting with pytest (we add dependencies to this below)
|
||||
add_custom_target(check DEPENDS pytest)
|
||||
|
||||
|
31
3rdparty/pybind11/tests/conftest.py
vendored
31
3rdparty/pybind11/tests/conftest.py
vendored
@ -1,8 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""pytest configuration
|
||||
|
||||
Extends output capture as needed by pybind11: ignore constructors, optional unordered lines.
|
||||
Adds docstring and exceptions message sanitizers: ignore Python 2 vs 3 differences.
|
||||
Adds docstring and exceptions message sanitizers.
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
@ -13,19 +12,14 @@ import textwrap
|
||||
|
||||
import pytest
|
||||
|
||||
import env
|
||||
|
||||
# Early diagnostic for failed imports
|
||||
import pybind11_tests # noqa: F401
|
||||
import pybind11_tests
|
||||
|
||||
_unicode_marker = re.compile(r"u(\'[^\']*\')")
|
||||
_long_marker = re.compile(r"([0-9])L")
|
||||
_hexadecimal = re.compile(r"0x[0-9a-fA-F]+")
|
||||
|
||||
# Avoid collecting Python3 only files
|
||||
collect_ignore = []
|
||||
if env.PY2:
|
||||
collect_ignore.append("test_async.py")
|
||||
|
||||
|
||||
def _strip_and_dedent(s):
|
||||
@ -45,7 +39,7 @@ def _make_explanation(a, b):
|
||||
]
|
||||
|
||||
|
||||
class Output(object):
|
||||
class Output:
|
||||
"""Basic output post-processing and comparison"""
|
||||
|
||||
def __init__(self, string):
|
||||
@ -83,7 +77,7 @@ class Unordered(Output):
|
||||
return False
|
||||
|
||||
|
||||
class Capture(object):
|
||||
class Capture:
|
||||
def __init__(self, capfd):
|
||||
self.capfd = capfd
|
||||
self.out = ""
|
||||
@ -126,7 +120,7 @@ def capture(capsys):
|
||||
return Capture(capsys)
|
||||
|
||||
|
||||
class SanitizedString(object):
|
||||
class SanitizedString:
|
||||
def __init__(self, sanitizer):
|
||||
self.sanitizer = sanitizer
|
||||
self.string = ""
|
||||
@ -149,9 +143,7 @@ class SanitizedString(object):
|
||||
def _sanitize_general(s):
|
||||
s = s.strip()
|
||||
s = s.replace("pybind11_tests.", "m.")
|
||||
s = s.replace("unicode", "str")
|
||||
s = _long_marker.sub(r"\1", s)
|
||||
s = _unicode_marker.sub(r"\1", s)
|
||||
return s
|
||||
|
||||
|
||||
@ -206,3 +198,16 @@ def gc_collect():
|
||||
def pytest_configure():
|
||||
pytest.suppress = suppress
|
||||
pytest.gc_collect = gc_collect
|
||||
|
||||
|
||||
def pytest_report_header(config):
|
||||
del config # Unused.
|
||||
assert (
|
||||
pybind11_tests.compiler_info is not None
|
||||
), "Please update pybind11_tests.cpp if this assert fails."
|
||||
return (
|
||||
"C++ Info:"
|
||||
f" {pybind11_tests.compiler_info}"
|
||||
f" {pybind11_tests.cpp_std}"
|
||||
f" {pybind11_tests.PYBIND11_INTERNALS_ID}"
|
||||
)
|
||||
|
143
3rdparty/pybind11/tests/constructor_stats.h
vendored
143
3rdparty/pybind11/tests/constructor_stats.h
vendored
@ -56,7 +56,8 @@ from the ConstructorStats instance `.values()` method.
|
||||
In some cases, when you need to track instances of a C++ class not registered with pybind11, you
|
||||
need to add a function returning the ConstructorStats for the C++ class; this can be done with:
|
||||
|
||||
m.def("get_special_cstats", &ConstructorStats::get<SpecialClass>, py::return_value_policy::reference)
|
||||
m.def("get_special_cstats", &ConstructorStats::get<SpecialClass>,
|
||||
py::return_value_policy::reference)
|
||||
|
||||
Finally, you can suppress the output messages, but keep the constructor tracking (for
|
||||
inspection/testing in python) by using the functions with `print_` replaced with `track_` (e.g.
|
||||
@ -65,15 +66,18 @@ inspection/testing in python) by using the functions with `print_` replaced with
|
||||
*/
|
||||
|
||||
#include "pybind11_tests.h"
|
||||
#include <unordered_map>
|
||||
|
||||
#include <list>
|
||||
#include <typeindex>
|
||||
#include <sstream>
|
||||
#include <typeindex>
|
||||
#include <unordered_map>
|
||||
|
||||
class ConstructorStats {
|
||||
protected:
|
||||
std::unordered_map<void*, int> _instances; // Need a map rather than set because members can shared address with parents
|
||||
std::list<std::string> _values; // Used to track values (e.g. of value constructors)
|
||||
std::unordered_map<void *, int> _instances; // Need a map rather than set because members can
|
||||
// shared address with parents
|
||||
std::list<std::string> _values; // Used to track values
|
||||
// (e.g. of value constructors)
|
||||
public:
|
||||
int default_constructions = 0;
|
||||
int copy_constructions = 0;
|
||||
@ -96,26 +100,26 @@ public:
|
||||
default_constructions++;
|
||||
}
|
||||
|
||||
void created(void *inst) {
|
||||
++_instances[inst];
|
||||
}
|
||||
void created(void *inst) { ++_instances[inst]; }
|
||||
|
||||
void destroyed(void *inst) {
|
||||
if (--_instances[inst] < 0)
|
||||
if (--_instances[inst] < 0) {
|
||||
throw std::runtime_error("cstats.destroyed() called with unknown "
|
||||
"instance; potential double-destruction "
|
||||
"or a missing cstats.created()");
|
||||
}
|
||||
}
|
||||
|
||||
static void gc() {
|
||||
// Force garbage collection to ensure any pending destructors are invoked:
|
||||
#if defined(PYPY_VERSION)
|
||||
PyObject *globals = PyEval_GetGlobals();
|
||||
PyObject *result = PyRun_String(
|
||||
"import gc\n"
|
||||
"for i in range(2):"
|
||||
" gc.collect()\n",
|
||||
Py_file_input, globals, globals);
|
||||
PyObject *result = PyRun_String("import gc\n"
|
||||
"for i in range(2):\n"
|
||||
" gc.collect()\n",
|
||||
Py_file_input,
|
||||
globals,
|
||||
globals);
|
||||
if (result == nullptr)
|
||||
throw py::error_already_set();
|
||||
Py_DECREF(result);
|
||||
@ -127,15 +131,18 @@ public:
|
||||
int alive() {
|
||||
gc();
|
||||
int total = 0;
|
||||
for (const auto &p : _instances)
|
||||
if (p.second > 0)
|
||||
for (const auto &p : _instances) {
|
||||
if (p.second > 0) {
|
||||
total += p.second;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
void value() {} // Recursion terminator
|
||||
// Takes one or more values, converts them to strings, then stores them.
|
||||
template <typename T, typename... Tmore> void value(const T &v, Tmore &&...args) {
|
||||
template <typename T, typename... Tmore>
|
||||
void value(const T &v, Tmore &&...args) {
|
||||
std::ostringstream oss;
|
||||
oss << v;
|
||||
_values.push_back(oss.str());
|
||||
@ -145,19 +152,22 @@ public:
|
||||
// Move out stored values
|
||||
py::list values() {
|
||||
py::list l;
|
||||
for (const auto &v : _values) l.append(py::cast(v));
|
||||
for (const auto &v : _values) {
|
||||
l.append(py::cast(v));
|
||||
}
|
||||
_values.clear();
|
||||
return l;
|
||||
}
|
||||
|
||||
// Gets constructor stats from a C++ type index
|
||||
static ConstructorStats& get(std::type_index type) {
|
||||
static ConstructorStats &get(std::type_index type) {
|
||||
static std::unordered_map<std::type_index, ConstructorStats> all_cstats;
|
||||
return all_cstats[type];
|
||||
}
|
||||
|
||||
// Gets constructor stats from a C++ type
|
||||
template <typename T> static ConstructorStats& get() {
|
||||
template <typename T>
|
||||
static ConstructorStats &get() {
|
||||
#if defined(PYPY_VERSION)
|
||||
gc();
|
||||
#endif
|
||||
@ -165,11 +175,12 @@ public:
|
||||
}
|
||||
|
||||
// Gets constructor stats from a Python class
|
||||
static ConstructorStats& get(py::object class_) {
|
||||
static ConstructorStats &get(py::object class_) {
|
||||
auto &internals = py::detail::get_internals();
|
||||
const std::type_index *t1 = nullptr, *t2 = nullptr;
|
||||
try {
|
||||
auto *type_info = internals.registered_types_py.at((PyTypeObject *) class_.ptr()).at(0);
|
||||
auto *type_info
|
||||
= internals.registered_types_py.at((PyTypeObject *) class_.ptr()).at(0);
|
||||
for (auto &p : internals.registered_types_cpp) {
|
||||
if (p.second == type_info) {
|
||||
if (t1) {
|
||||
@ -179,17 +190,23 @@ public:
|
||||
t1 = &p.first;
|
||||
}
|
||||
}
|
||||
} catch (const std::out_of_range &) {
|
||||
}
|
||||
if (!t1) {
|
||||
throw std::runtime_error("Unknown class passed to ConstructorStats::get()");
|
||||
}
|
||||
catch (const std::out_of_range&) {}
|
||||
if (!t1) throw std::runtime_error("Unknown class passed to ConstructorStats::get()");
|
||||
auto &cs1 = get(*t1);
|
||||
// If we have both a t1 and t2 match, one is probably the trampoline class; return whichever
|
||||
// has more constructions (typically one or the other will be 0)
|
||||
// If we have both a t1 and t2 match, one is probably the trampoline class; return
|
||||
// whichever has more constructions (typically one or the other will be 0)
|
||||
if (t2) {
|
||||
auto &cs2 = get(*t2);
|
||||
int cs1_total = cs1.default_constructions + cs1.copy_constructions + cs1.move_constructions + (int) cs1._values.size();
|
||||
int cs2_total = cs2.default_constructions + cs2.copy_constructions + cs2.move_constructions + (int) cs2._values.size();
|
||||
if (cs2_total > cs1_total) return cs2;
|
||||
int cs1_total = cs1.default_constructions + cs1.copy_constructions
|
||||
+ cs1.move_constructions + (int) cs1._values.size();
|
||||
int cs2_total = cs2.default_constructions + cs2.copy_constructions
|
||||
+ cs2.move_constructions + (int) cs2._values.size();
|
||||
if (cs2_total > cs1_total) {
|
||||
return cs2;
|
||||
}
|
||||
}
|
||||
return cs1;
|
||||
}
|
||||
@ -198,78 +215,108 @@ public:
|
||||
// To track construction/destruction, you need to call these methods from the various
|
||||
// constructors/operators. The ones that take extra values record the given values in the
|
||||
// constructor stats values for later inspection.
|
||||
template <class T> void track_copy_created(T *inst) { ConstructorStats::get<T>().copy_created(inst); }
|
||||
template <class T> void track_move_created(T *inst) { ConstructorStats::get<T>().move_created(inst); }
|
||||
template <class T, typename... Values> void track_copy_assigned(T *, Values &&...values) {
|
||||
template <class T>
|
||||
void track_copy_created(T *inst) {
|
||||
ConstructorStats::get<T>().copy_created(inst);
|
||||
}
|
||||
template <class T>
|
||||
void track_move_created(T *inst) {
|
||||
ConstructorStats::get<T>().move_created(inst);
|
||||
}
|
||||
template <class T, typename... Values>
|
||||
void track_copy_assigned(T *, Values &&...values) {
|
||||
auto &cst = ConstructorStats::get<T>();
|
||||
cst.copy_assignments++;
|
||||
cst.value(std::forward<Values>(values)...);
|
||||
}
|
||||
template <class T, typename... Values> void track_move_assigned(T *, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void track_move_assigned(T *, Values &&...values) {
|
||||
auto &cst = ConstructorStats::get<T>();
|
||||
cst.move_assignments++;
|
||||
cst.value(std::forward<Values>(values)...);
|
||||
}
|
||||
template <class T, typename... Values> void track_default_created(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void track_default_created(T *inst, Values &&...values) {
|
||||
auto &cst = ConstructorStats::get<T>();
|
||||
cst.default_created(inst);
|
||||
cst.value(std::forward<Values>(values)...);
|
||||
}
|
||||
template <class T, typename... Values> void track_created(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void track_created(T *inst, Values &&...values) {
|
||||
auto &cst = ConstructorStats::get<T>();
|
||||
cst.created(inst);
|
||||
cst.value(std::forward<Values>(values)...);
|
||||
}
|
||||
template <class T, typename... Values> void track_destroyed(T *inst) {
|
||||
template <class T, typename... Values>
|
||||
void track_destroyed(T *inst) {
|
||||
ConstructorStats::get<T>().destroyed(inst);
|
||||
}
|
||||
template <class T, typename... Values> void track_values(T *, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void track_values(T *, Values &&...values) {
|
||||
ConstructorStats::get<T>().value(std::forward<Values>(values)...);
|
||||
}
|
||||
|
||||
/// Don't cast pointers to Python, print them as strings
|
||||
inline const char *format_ptrs(const char *p) { return p; }
|
||||
template <typename T>
|
||||
py::str format_ptrs(T *p) { return "{:#x}"_s.format(reinterpret_cast<std::uintptr_t>(p)); }
|
||||
py::str format_ptrs(T *p) {
|
||||
return "{:#x}"_s.format(reinterpret_cast<std::uintptr_t>(p));
|
||||
}
|
||||
template <typename T>
|
||||
auto format_ptrs(T &&x) -> decltype(std::forward<T>(x)) { return std::forward<T>(x); }
|
||||
auto format_ptrs(T &&x) -> decltype(std::forward<T>(x)) {
|
||||
return std::forward<T>(x);
|
||||
}
|
||||
|
||||
template <class T, typename... Output>
|
||||
void print_constr_details(T *inst, const std::string &action, Output &&...output) {
|
||||
py::print("###", py::type_id<T>(), "@", format_ptrs(inst), action,
|
||||
py::print("###",
|
||||
py::type_id<T>(),
|
||||
"@",
|
||||
format_ptrs(inst),
|
||||
action,
|
||||
format_ptrs(std::forward<Output>(output))...);
|
||||
}
|
||||
|
||||
// Verbose versions of the above:
|
||||
template <class T, typename... Values> void print_copy_created(T *inst, Values &&...values) { // NB: this prints, but doesn't store, given values
|
||||
template <class T, typename... Values>
|
||||
void print_copy_created(T *inst,
|
||||
Values &&...values) { // NB: this prints, but doesn't store, given values
|
||||
print_constr_details(inst, "created via copy constructor", values...);
|
||||
track_copy_created(inst);
|
||||
}
|
||||
template <class T, typename... Values> void print_move_created(T *inst, Values &&...values) { // NB: this prints, but doesn't store, given values
|
||||
template <class T, typename... Values>
|
||||
void print_move_created(T *inst,
|
||||
Values &&...values) { // NB: this prints, but doesn't store, given values
|
||||
print_constr_details(inst, "created via move constructor", values...);
|
||||
track_move_created(inst);
|
||||
}
|
||||
template <class T, typename... Values> void print_copy_assigned(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void print_copy_assigned(T *inst, Values &&...values) {
|
||||
print_constr_details(inst, "assigned via copy assignment", values...);
|
||||
track_copy_assigned(inst, values...);
|
||||
}
|
||||
template <class T, typename... Values> void print_move_assigned(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void print_move_assigned(T *inst, Values &&...values) {
|
||||
print_constr_details(inst, "assigned via move assignment", values...);
|
||||
track_move_assigned(inst, values...);
|
||||
}
|
||||
template <class T, typename... Values> void print_default_created(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void print_default_created(T *inst, Values &&...values) {
|
||||
print_constr_details(inst, "created via default constructor", values...);
|
||||
track_default_created(inst, values...);
|
||||
}
|
||||
template <class T, typename... Values> void print_created(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void print_created(T *inst, Values &&...values) {
|
||||
print_constr_details(inst, "created", values...);
|
||||
track_created(inst, values...);
|
||||
}
|
||||
template <class T, typename... Values> void print_destroyed(T *inst, Values &&...values) { // Prints but doesn't store given values
|
||||
template <class T, typename... Values>
|
||||
void print_destroyed(T *inst, Values &&...values) { // Prints but doesn't store given values
|
||||
print_constr_details(inst, "destroyed", values...);
|
||||
track_destroyed(inst);
|
||||
}
|
||||
template <class T, typename... Values> void print_values(T *inst, Values &&...values) {
|
||||
template <class T, typename... Values>
|
||||
void print_values(T *inst, Values &&...values) {
|
||||
print_constr_details(inst, ":", values...);
|
||||
track_values(inst, values...);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
// This file mimics a DSO that makes pybind11 calls but does not define a
|
||||
@ -24,50 +25,21 @@ void gil_acquire() { py::gil_scoped_acquire gil; }
|
||||
|
||||
constexpr char kModuleName[] = "cross_module_gil_utils";
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
kModuleName,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
#else
|
||||
PyMethodDef module_methods[] = {
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
#endif
|
||||
PyModuleDef_HEAD_INIT, kModuleName, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
extern "C" PYBIND11_EXPORT
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* PyInit_cross_module_gil_utils()
|
||||
#else
|
||||
void initcross_module_gil_utils()
|
||||
#endif
|
||||
{
|
||||
extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_gil_utils() {
|
||||
|
||||
PyObject* m =
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyModule_Create(&moduledef);
|
||||
#else
|
||||
Py_InitModule(kModuleName, module_methods);
|
||||
#endif
|
||||
PyObject *m = PyModule_Create(&moduledef);
|
||||
|
||||
if (m != NULL) {
|
||||
static_assert(
|
||||
sizeof(&gil_acquire) == sizeof(void*),
|
||||
"Function pointer must have the same size as void*");
|
||||
PyModule_AddObject(m, "gil_acquire_funcaddr",
|
||||
PyLong_FromVoidPtr(reinterpret_cast<void*>(&gil_acquire)));
|
||||
if (m != nullptr) {
|
||||
static_assert(sizeof(&gil_acquire) == sizeof(void *),
|
||||
"Function pointer must have the same size as void*");
|
||||
PyModule_AddObject(
|
||||
m, "gil_acquire_funcaddr", PyLong_FromVoidPtr(reinterpret_cast<void *>(&gil_acquire)));
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return m;
|
||||
#endif
|
||||
}
|
||||
|
51
3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp
vendored
Normal file
51
3rdparty/pybind11/tests/cross_module_interleaved_error_already_set.cpp
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright (c) 2022 Google LLC
|
||||
|
||||
All rights reserved. Use of this source code is governed by a
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
// This file mimics a DSO that makes pybind11 calls but does not define a PYBIND11_MODULE,
|
||||
// so that the first call of cross_module_error_already_set() triggers the first call of
|
||||
// pybind11::detail::get_internals().
|
||||
|
||||
namespace {
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
void interleaved_error_already_set() {
|
||||
PyErr_SetString(PyExc_RuntimeError, "1st error.");
|
||||
try {
|
||||
throw py::error_already_set();
|
||||
} catch (const py::error_already_set &) {
|
||||
// The 2nd error could be conditional in a real application.
|
||||
PyErr_SetString(PyExc_RuntimeError, "2nd error.");
|
||||
} // Here the 1st error is destroyed before the 2nd error is fetched.
|
||||
// The error_already_set dtor triggers a pybind11::detail::get_internals()
|
||||
// call via pybind11::gil_scoped_acquire.
|
||||
if (PyErr_Occurred()) {
|
||||
throw py::error_already_set();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr char kModuleName[] = "cross_module_interleaved_error_already_set";
|
||||
|
||||
struct PyModuleDef moduledef = {
|
||||
PyModuleDef_HEAD_INIT, kModuleName, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr};
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_interleaved_error_already_set() {
|
||||
PyObject *m = PyModule_Create(&moduledef);
|
||||
if (m != nullptr) {
|
||||
static_assert(sizeof(&interleaved_error_already_set) == sizeof(void *),
|
||||
"Function pointer must have the same size as void *");
|
||||
PyModule_AddObject(
|
||||
m,
|
||||
"funcaddr",
|
||||
PyLong_FromVoidPtr(reinterpret_cast<void *>(&interleaved_error_already_set)));
|
||||
}
|
||||
return m;
|
||||
}
|
20
3rdparty/pybind11/tests/env.py
vendored
20
3rdparty/pybind11/tests/env.py
vendored
@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import platform
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
LINUX = sys.platform.startswith("linux")
|
||||
MACOS = sys.platform.startswith("darwin")
|
||||
WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
|
||||
@ -9,6 +10,19 @@ WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
|
||||
CPYTHON = platform.python_implementation() == "CPython"
|
||||
PYPY = platform.python_implementation() == "PyPy"
|
||||
|
||||
PY2 = sys.version_info.major == 2
|
||||
|
||||
PY = sys.version_info
|
||||
def deprecated_call():
|
||||
"""
|
||||
pytest.deprecated_call() seems broken in pytest<3.9.x; concretely, it
|
||||
doesn't work on CPython 3.8.0 with pytest==3.3.2 on Ubuntu 18.04 (#2922).
|
||||
|
||||
This is a narrowed reimplementation of the following PR :(
|
||||
https://github.com/pytest-dev/pytest/pull/4104
|
||||
"""
|
||||
# TODO: Remove this when testing requires pytest>=3.9.
|
||||
pieces = pytest.__version__.split(".")
|
||||
pytest_major_minor = (int(pieces[0]), int(pieces[1]))
|
||||
if pytest_major_minor < (3, 9):
|
||||
return pytest.warns((DeprecationWarning, PendingDeprecationWarning))
|
||||
else:
|
||||
return pytest.deprecated_call()
|
||||
|
@ -1,4 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import contextlib
|
||||
import os
|
||||
import string
|
||||
@ -13,6 +12,16 @@ import zipfile
|
||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
|
||||
|
||||
PKGCONFIG = """\
|
||||
prefix=${{pcfiledir}}/../../
|
||||
includedir=${{prefix}}/include
|
||||
|
||||
Name: pybind11
|
||||
Description: Seamless operability between C++11 and Python
|
||||
Version: {VERSION}
|
||||
Cflags: -I${{includedir}}
|
||||
"""
|
||||
|
||||
|
||||
main_headers = {
|
||||
"include/pybind11/attr.h",
|
||||
@ -25,6 +34,7 @@ main_headers = {
|
||||
"include/pybind11/embed.h",
|
||||
"include/pybind11/eval.h",
|
||||
"include/pybind11/functional.h",
|
||||
"include/pybind11/gil.h",
|
||||
"include/pybind11/iostream.h",
|
||||
"include/pybind11/numpy.h",
|
||||
"include/pybind11/operators.h",
|
||||
@ -41,9 +51,14 @@ detail_headers = {
|
||||
"include/pybind11/detail/descr.h",
|
||||
"include/pybind11/detail/init.h",
|
||||
"include/pybind11/detail/internals.h",
|
||||
"include/pybind11/detail/type_caster_base.h",
|
||||
"include/pybind11/detail/typeid.h",
|
||||
}
|
||||
|
||||
stl_headers = {
|
||||
"include/pybind11/stl/filesystem.h",
|
||||
}
|
||||
|
||||
cmake_files = {
|
||||
"share/cmake/pybind11/FindPythonLibsNew.cmake",
|
||||
"share/cmake/pybind11/pybind11Common.cmake",
|
||||
@ -54,19 +69,21 @@ cmake_files = {
|
||||
"share/cmake/pybind11/pybind11Tools.cmake",
|
||||
}
|
||||
|
||||
pkgconfig_files = {
|
||||
"share/pkgconfig/pybind11.pc",
|
||||
}
|
||||
|
||||
py_files = {
|
||||
"__init__.py",
|
||||
"__main__.py",
|
||||
"_version.py",
|
||||
"_version.pyi",
|
||||
"commands.py",
|
||||
"py.typed",
|
||||
"setup_helpers.py",
|
||||
"setup_helpers.pyi",
|
||||
}
|
||||
|
||||
headers = main_headers | detail_headers
|
||||
src_files = headers | cmake_files
|
||||
headers = main_headers | detail_headers | stl_headers
|
||||
src_files = headers | cmake_files | pkgconfig_files
|
||||
all_files = src_files | py_files
|
||||
|
||||
|
||||
@ -75,9 +92,11 @@ sdist_files = {
|
||||
"pybind11/include",
|
||||
"pybind11/include/pybind11",
|
||||
"pybind11/include/pybind11/detail",
|
||||
"pybind11/include/pybind11/stl",
|
||||
"pybind11/share",
|
||||
"pybind11/share/cmake",
|
||||
"pybind11/share/cmake/pybind11",
|
||||
"pybind11/share/pkgconfig",
|
||||
"pyproject.toml",
|
||||
"setup.cfg",
|
||||
"setup.py",
|
||||
@ -97,105 +116,106 @@ local_sdist_files = {
|
||||
}
|
||||
|
||||
|
||||
def read_tz_file(tar: tarfile.TarFile, name: str) -> bytes:
|
||||
start = tar.getnames()[0] + "/"
|
||||
inner_file = tar.extractfile(tar.getmember(f"{start}{name}"))
|
||||
assert inner_file
|
||||
with contextlib.closing(inner_file) as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def normalize_line_endings(value: bytes) -> bytes:
|
||||
return value.replace(os.linesep.encode("utf-8"), b"\n")
|
||||
|
||||
|
||||
def test_build_sdist(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.chdir(MAIN_DIR)
|
||||
|
||||
out = subprocess.check_output(
|
||||
[
|
||||
sys.executable,
|
||||
"setup.py",
|
||||
"sdist",
|
||||
"--formats=tar",
|
||||
"--dist-dir",
|
||||
str(tmpdir),
|
||||
]
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "build", "--sdist", f"--outdir={tmpdir}"], check=True
|
||||
)
|
||||
if hasattr(out, "decode"):
|
||||
out = out.decode()
|
||||
|
||||
(sdist,) = tmpdir.visit("*.tar")
|
||||
(sdist,) = tmpdir.visit("*.tar.gz")
|
||||
|
||||
with tarfile.open(str(sdist)) as tar:
|
||||
with tarfile.open(str(sdist), "r:gz") as tar:
|
||||
start = tar.getnames()[0] + "/"
|
||||
version = start[9:-1]
|
||||
simpler = set(n.split("/", 1)[-1] for n in tar.getnames()[1:])
|
||||
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
|
||||
|
||||
with contextlib.closing(
|
||||
tar.extractfile(tar.getmember(start + "setup.py"))
|
||||
) as f:
|
||||
setup_py = f.read()
|
||||
setup_py = read_tz_file(tar, "setup.py")
|
||||
pyproject_toml = read_tz_file(tar, "pyproject.toml")
|
||||
pkgconfig = read_tz_file(tar, "pybind11/share/pkgconfig/pybind11.pc")
|
||||
cmake_cfg = read_tz_file(
|
||||
tar, "pybind11/share/cmake/pybind11/pybind11Config.cmake"
|
||||
)
|
||||
|
||||
with contextlib.closing(
|
||||
tar.extractfile(tar.getmember(start + "pyproject.toml"))
|
||||
) as f:
|
||||
pyproject_toml = f.read()
|
||||
assert (
|
||||
'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")'
|
||||
in cmake_cfg.decode("utf-8")
|
||||
)
|
||||
|
||||
files = set("pybind11/{}".format(n) for n in all_files)
|
||||
files = {f"pybind11/{n}" for n in all_files}
|
||||
files |= sdist_files
|
||||
files |= set("pybind11{}".format(n) for n in local_sdist_files)
|
||||
files |= {f"pybind11{n}" for n in local_sdist_files}
|
||||
files.add("pybind11.egg-info/entry_points.txt")
|
||||
files.add("pybind11.egg-info/requires.txt")
|
||||
assert simpler == files
|
||||
|
||||
with open(os.path.join(MAIN_DIR, "tools", "setup_main.py.in"), "rb") as f:
|
||||
contents = (
|
||||
string.Template(f.read().decode())
|
||||
string.Template(f.read().decode("utf-8"))
|
||||
.substitute(version=version, extra_cmd="")
|
||||
.encode()
|
||||
.encode("utf-8")
|
||||
)
|
||||
assert setup_py == contents
|
||||
assert setup_py == contents
|
||||
|
||||
with open(os.path.join(MAIN_DIR, "tools", "pyproject.toml"), "rb") as f:
|
||||
contents = f.read()
|
||||
assert pyproject_toml == contents
|
||||
assert pyproject_toml == contents
|
||||
|
||||
simple_version = ".".join(version.split(".")[:3])
|
||||
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version).encode("utf-8")
|
||||
assert normalize_line_endings(pkgconfig) == pkgconfig_expected
|
||||
|
||||
|
||||
def test_build_global_dist(monkeypatch, tmpdir):
|
||||
|
||||
monkeypatch.chdir(MAIN_DIR)
|
||||
monkeypatch.setenv("PYBIND11_GLOBAL_SDIST", "1")
|
||||
|
||||
out = subprocess.check_output(
|
||||
[
|
||||
sys.executable,
|
||||
"setup.py",
|
||||
"sdist",
|
||||
"--formats=tar",
|
||||
"--dist-dir",
|
||||
str(tmpdir),
|
||||
]
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "build", "--sdist", "--outdir", str(tmpdir)], check=True
|
||||
)
|
||||
if hasattr(out, "decode"):
|
||||
out = out.decode()
|
||||
|
||||
(sdist,) = tmpdir.visit("*.tar")
|
||||
(sdist,) = tmpdir.visit("*.tar.gz")
|
||||
|
||||
with tarfile.open(str(sdist)) as tar:
|
||||
with tarfile.open(str(sdist), "r:gz") as tar:
|
||||
start = tar.getnames()[0] + "/"
|
||||
version = start[16:-1]
|
||||
simpler = set(n.split("/", 1)[-1] for n in tar.getnames()[1:])
|
||||
simpler = {n.split("/", 1)[-1] for n in tar.getnames()[1:]}
|
||||
|
||||
with contextlib.closing(
|
||||
tar.extractfile(tar.getmember(start + "setup.py"))
|
||||
) as f:
|
||||
setup_py = f.read()
|
||||
setup_py = read_tz_file(tar, "setup.py")
|
||||
pyproject_toml = read_tz_file(tar, "pyproject.toml")
|
||||
pkgconfig = read_tz_file(tar, "pybind11/share/pkgconfig/pybind11.pc")
|
||||
cmake_cfg = read_tz_file(
|
||||
tar, "pybind11/share/cmake/pybind11/pybind11Config.cmake"
|
||||
)
|
||||
|
||||
with contextlib.closing(
|
||||
tar.extractfile(tar.getmember(start + "pyproject.toml"))
|
||||
) as f:
|
||||
pyproject_toml = f.read()
|
||||
assert (
|
||||
'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")'
|
||||
in cmake_cfg.decode("utf-8")
|
||||
)
|
||||
|
||||
files = set("pybind11/{}".format(n) for n in all_files)
|
||||
files = {f"pybind11/{n}" for n in all_files}
|
||||
files |= sdist_files
|
||||
files |= set("pybind11_global{}".format(n) for n in local_sdist_files)
|
||||
files |= {f"pybind11_global{n}" for n in local_sdist_files}
|
||||
assert simpler == files
|
||||
|
||||
with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f:
|
||||
contents = (
|
||||
string.Template(f.read().decode())
|
||||
.substitute(version=version, extra_cmd="")
|
||||
.encode()
|
||||
.encode("utf-8")
|
||||
)
|
||||
assert setup_py == contents
|
||||
|
||||
@ -203,17 +223,21 @@ def test_build_global_dist(monkeypatch, tmpdir):
|
||||
contents = f.read()
|
||||
assert pyproject_toml == contents
|
||||
|
||||
simple_version = ".".join(version.split(".")[:3])
|
||||
pkgconfig_expected = PKGCONFIG.format(VERSION=simple_version).encode("utf-8")
|
||||
assert normalize_line_endings(pkgconfig) == pkgconfig_expected
|
||||
|
||||
|
||||
def tests_build_wheel(monkeypatch, tmpdir):
|
||||
monkeypatch.chdir(MAIN_DIR)
|
||||
|
||||
subprocess.check_output(
|
||||
[sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)]
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)], check=True
|
||||
)
|
||||
|
||||
(wheel,) = tmpdir.visit("*.whl")
|
||||
|
||||
files = set("pybind11/{}".format(n) for n in all_files)
|
||||
files = {f"pybind11/{n}" for n in all_files}
|
||||
files |= {
|
||||
"dist-info/LICENSE",
|
||||
"dist-info/METADATA",
|
||||
@ -226,10 +250,8 @@ def tests_build_wheel(monkeypatch, tmpdir):
|
||||
with zipfile.ZipFile(str(wheel)) as z:
|
||||
names = z.namelist()
|
||||
|
||||
trimmed = set(n for n in names if "dist-info" not in n)
|
||||
trimmed |= set(
|
||||
"dist-info/{}".format(n.split("/", 1)[-1]) for n in names if "dist-info" in n
|
||||
)
|
||||
trimmed = {n for n in names if "dist-info" not in n}
|
||||
trimmed |= {f"dist-info/{n.split('/', 1)[-1]}" for n in names if "dist-info" in n}
|
||||
assert files == trimmed
|
||||
|
||||
|
||||
@ -237,14 +259,14 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
|
||||
monkeypatch.chdir(MAIN_DIR)
|
||||
monkeypatch.setenv("PYBIND11_GLOBAL_SDIST", "1")
|
||||
|
||||
subprocess.check_output(
|
||||
[sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)]
|
||||
subprocess.run(
|
||||
[sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)], check=True
|
||||
)
|
||||
|
||||
(wheel,) = tmpdir.visit("*.whl")
|
||||
|
||||
files = set("data/data/{}".format(n) for n in src_files)
|
||||
files |= set("data/headers/{}".format(n[8:]) for n in headers)
|
||||
files = {f"data/data/{n}" for n in src_files}
|
||||
files |= {f"data/headers/{n[8:]}" for n in headers}
|
||||
files |= {
|
||||
"dist-info/LICENSE",
|
||||
"dist-info/METADATA",
|
||||
@ -257,6 +279,6 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
|
||||
names = z.namelist()
|
||||
|
||||
beginning = names[0].split("/", 1)[0].rsplit(".", 1)[0]
|
||||
trimmed = set(n[len(beginning) + 1 :] for n in names)
|
||||
trimmed = {n[len(beginning) + 1 :] for n in names}
|
||||
|
||||
assert files == trimmed
|
||||
|
@ -1,13 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
import sys
|
||||
from textwrap import dedent
|
||||
|
||||
import pytest
|
||||
|
||||
DIR = os.path.abspath(os.path.dirname(__file__))
|
||||
MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
|
||||
WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("parallel", [False, True])
|
||||
@ -18,7 +18,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
|
||||
(tmpdir / "setup.py").write_text(
|
||||
dedent(
|
||||
u"""\
|
||||
f"""\
|
||||
import sys
|
||||
sys.path.append({MAIN_DIR!r})
|
||||
|
||||
@ -51,13 +51,13 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
ext_modules=ext_modules,
|
||||
)
|
||||
"""
|
||||
).format(MAIN_DIR=MAIN_DIR, std=std, parallel=parallel),
|
||||
),
|
||||
encoding="ascii",
|
||||
)
|
||||
|
||||
(tmpdir / "main.cpp").write_text(
|
||||
dedent(
|
||||
u"""\
|
||||
"""\
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
int f(int x) {
|
||||
@ -71,13 +71,20 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
encoding="ascii",
|
||||
)
|
||||
|
||||
subprocess.check_call(
|
||||
out = subprocess.check_output(
|
||||
[sys.executable, "setup.py", "build_ext", "--inplace"],
|
||||
stdout=sys.stdout,
|
||||
stderr=sys.stderr,
|
||||
)
|
||||
if not WIN:
|
||||
assert b"-g0" in out
|
||||
out = subprocess.check_output(
|
||||
[sys.executable, "setup.py", "build_ext", "--inplace", "--force"],
|
||||
env=dict(os.environ, CFLAGS="-g"),
|
||||
)
|
||||
if not WIN:
|
||||
assert b"-g0" not in out
|
||||
|
||||
# Debug helper printout, normally hidden
|
||||
print(out)
|
||||
for item in tmpdir.listdir():
|
||||
print(item.basename)
|
||||
|
||||
@ -88,7 +95,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
|
||||
(tmpdir / "test.py").write_text(
|
||||
dedent(
|
||||
u"""\
|
||||
"""\
|
||||
import simple_setup
|
||||
assert simple_setup.f(3) == 9
|
||||
"""
|
||||
@ -99,3 +106,46 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
subprocess.check_call(
|
||||
[sys.executable, "test.py"], stdout=sys.stdout, stderr=sys.stderr
|
||||
)
|
||||
|
||||
|
||||
def test_intree_extensions(monkeypatch, tmpdir):
|
||||
monkeypatch.syspath_prepend(MAIN_DIR)
|
||||
|
||||
from pybind11.setup_helpers import intree_extensions
|
||||
|
||||
monkeypatch.chdir(tmpdir)
|
||||
root = tmpdir
|
||||
root.ensure_dir()
|
||||
subdir = root / "dir"
|
||||
subdir.ensure_dir()
|
||||
src = subdir / "ext.cpp"
|
||||
src.ensure()
|
||||
relpath = src.relto(tmpdir)
|
||||
(ext,) = intree_extensions([relpath])
|
||||
assert ext.name == "ext"
|
||||
subdir.ensure("__init__.py")
|
||||
(ext,) = intree_extensions([relpath])
|
||||
assert ext.name == "dir.ext"
|
||||
|
||||
|
||||
def test_intree_extensions_package_dir(monkeypatch, tmpdir):
|
||||
monkeypatch.syspath_prepend(MAIN_DIR)
|
||||
|
||||
from pybind11.setup_helpers import intree_extensions
|
||||
|
||||
monkeypatch.chdir(tmpdir)
|
||||
root = tmpdir / "src"
|
||||
root.ensure_dir()
|
||||
subdir = root / "dir"
|
||||
subdir.ensure_dir()
|
||||
src = subdir / "ext.cpp"
|
||||
src.ensure()
|
||||
(ext,) = intree_extensions([src.relto(tmpdir)], package_dir={"": "src"})
|
||||
assert ext.name == "dir.ext"
|
||||
(ext,) = intree_extensions([src.relto(tmpdir)], package_dir={"foo": "src"})
|
||||
assert ext.name == "foo.dir.ext"
|
||||
subdir.ensure("__init__.py")
|
||||
(ext,) = intree_extensions([src.relto(tmpdir)], package_dir={"": "src"})
|
||||
assert ext.name == "dir.ext"
|
||||
(ext,) = intree_extensions([src.relto(tmpdir)], package_dir={"foo": "src"})
|
||||
assert ext.name == "foo.dir.ext"
|
||||
|
52
3rdparty/pybind11/tests/local_bindings.h
vendored
52
3rdparty/pybind11/tests/local_bindings.h
vendored
@ -1,10 +1,13 @@
|
||||
#pragma once
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
/// Simple class used to test py::local:
|
||||
template <int> class LocalBase {
|
||||
template <int>
|
||||
class LocalBase {
|
||||
public:
|
||||
LocalBase(int i) : i(i) { }
|
||||
explicit LocalBase(int i) : i(i) {}
|
||||
int i = -1;
|
||||
};
|
||||
|
||||
@ -33,32 +36,57 @@ using NonLocalVec2 = std::vector<NonLocal2>;
|
||||
using NonLocalMap = std::unordered_map<std::string, NonLocalType>;
|
||||
using NonLocalMap2 = std::unordered_map<std::string, uint8_t>;
|
||||
|
||||
// Exception that will be caught via the module local translator.
|
||||
class LocalException : public std::exception {
|
||||
public:
|
||||
explicit LocalException(const char *m) : message{m} {}
|
||||
const char *what() const noexcept override { return message.c_str(); }
|
||||
|
||||
private:
|
||||
std::string message = "";
|
||||
};
|
||||
|
||||
// Exception that will be registered with register_local_exception_translator
|
||||
class LocalSimpleException : public std::exception {
|
||||
public:
|
||||
explicit LocalSimpleException(const char *m) : message{m} {}
|
||||
const char *what() const noexcept override { return message.c_str(); }
|
||||
|
||||
private:
|
||||
std::string message = "";
|
||||
};
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(LocalVec);
|
||||
PYBIND11_MAKE_OPAQUE(LocalVec2);
|
||||
PYBIND11_MAKE_OPAQUE(LocalMap);
|
||||
PYBIND11_MAKE_OPAQUE(NonLocalVec);
|
||||
//PYBIND11_MAKE_OPAQUE(NonLocalVec2); // same type as LocalVec2
|
||||
// PYBIND11_MAKE_OPAQUE(NonLocalVec2); // same type as LocalVec2
|
||||
PYBIND11_MAKE_OPAQUE(NonLocalMap);
|
||||
PYBIND11_MAKE_OPAQUE(NonLocalMap2);
|
||||
|
||||
|
||||
// Simple bindings (used with the above):
|
||||
template <typename T, int Adjust = 0, typename... Args>
|
||||
py::class_<T> bind_local(Args && ...args) {
|
||||
return py::class_<T>(std::forward<Args>(args)...)
|
||||
.def(py::init<int>())
|
||||
.def("get", [](T &i) { return i.i + Adjust; });
|
||||
py::class_<T> bind_local(Args &&...args) {
|
||||
return py::class_<T>(std::forward<Args>(args)...).def(py::init<int>()).def("get", [](T &i) {
|
||||
return i.i + Adjust;
|
||||
});
|
||||
};
|
||||
|
||||
// Simulate a foreign library base class (to match the example in the docs):
|
||||
namespace pets {
|
||||
class Pet {
|
||||
public:
|
||||
Pet(std::string name) : name_(name) {}
|
||||
explicit Pet(std::string name) : name_(std::move(name)) {}
|
||||
std::string name_;
|
||||
const std::string &name() { return name_; }
|
||||
const std::string &name() const { return name_; }
|
||||
};
|
||||
} // namespace pets
|
||||
|
||||
struct MixGL { int i; MixGL(int i) : i{i} {} };
|
||||
struct MixGL2 { int i; MixGL2(int i) : i{i} {} };
|
||||
struct MixGL {
|
||||
int i;
|
||||
explicit MixGL(int i) : i{i} {}
|
||||
};
|
||||
struct MixGL2 {
|
||||
int i;
|
||||
explicit MixGL2(int i) : i{i} {}
|
||||
};
|
||||
|
114
3rdparty/pybind11/tests/object.h
vendored
114
3rdparty/pybind11/tests/object.h
vendored
@ -1,8 +1,9 @@
|
||||
#if !defined(__OBJECT_H)
|
||||
#define __OBJECT_H
|
||||
# define __OBJECT_H
|
||||
|
||||
#include <atomic>
|
||||
#include "constructor_stats.h"
|
||||
# include "constructor_stats.h"
|
||||
|
||||
# include <atomic>
|
||||
|
||||
/// Reference counted object base class
|
||||
class Object {
|
||||
@ -27,20 +28,23 @@ public:
|
||||
*/
|
||||
void decRef(bool dealloc = true) const {
|
||||
--m_refCount;
|
||||
if (m_refCount == 0 && dealloc)
|
||||
if (m_refCount == 0 && dealloc) {
|
||||
delete this;
|
||||
else if (m_refCount < 0)
|
||||
} else if (m_refCount < 0) {
|
||||
throw std::runtime_error("Internal error: reference count < 0!");
|
||||
}
|
||||
}
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
|
||||
protected:
|
||||
/** \brief Virtual protected deconstructor.
|
||||
* (Will only be called by \ref ref)
|
||||
*/
|
||||
virtual ~Object() { print_destroyed(this); }
|
||||
|
||||
private:
|
||||
mutable std::atomic<int> m_refCount { 0 };
|
||||
mutable std::atomic<int> m_refCount{0};
|
||||
};
|
||||
|
||||
// Tag class used to track constructions of ref objects. When we track constructors, below, we
|
||||
@ -59,80 +63,105 @@ class ref_tag {};
|
||||
*
|
||||
* \ingroup libcore
|
||||
*/
|
||||
template <typename T> class ref {
|
||||
template <typename T>
|
||||
class ref {
|
||||
public:
|
||||
/// Create a nullptr reference
|
||||
ref() : m_ptr(nullptr) { print_default_created(this); track_default_created((ref_tag*) this); }
|
||||
ref() : m_ptr(nullptr) {
|
||||
print_default_created(this);
|
||||
track_default_created((ref_tag *) this);
|
||||
}
|
||||
|
||||
/// Construct a reference from a pointer
|
||||
ref(T *ptr) : m_ptr(ptr) {
|
||||
if (m_ptr) ((Object *) m_ptr)->incRef();
|
||||
|
||||
print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer");
|
||||
explicit ref(T *ptr) : m_ptr(ptr) {
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
|
||||
print_created(this, "from pointer", m_ptr);
|
||||
track_created((ref_tag *) this, "from pointer");
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
ref(const ref &r) : m_ptr(r.m_ptr) {
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
|
||||
print_copy_created(this, "with pointer", m_ptr); track_copy_created((ref_tag*) this);
|
||||
print_copy_created(this, "with pointer", m_ptr);
|
||||
track_copy_created((ref_tag *) this);
|
||||
}
|
||||
|
||||
/// Move constructor
|
||||
ref(ref &&r) : m_ptr(r.m_ptr) {
|
||||
ref(ref &&r) noexcept : m_ptr(r.m_ptr) {
|
||||
r.m_ptr = nullptr;
|
||||
|
||||
print_move_created(this, "with pointer", m_ptr); track_move_created((ref_tag*) this);
|
||||
print_move_created(this, "with pointer", m_ptr);
|
||||
track_move_created((ref_tag *) this);
|
||||
}
|
||||
|
||||
/// Destroy this reference
|
||||
~ref() {
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
|
||||
print_destroyed(this); track_destroyed((ref_tag*) this);
|
||||
print_destroyed(this);
|
||||
track_destroyed((ref_tag *) this);
|
||||
}
|
||||
|
||||
/// Move another reference into the current one
|
||||
ref& operator=(ref&& r) {
|
||||
print_move_assigned(this, "pointer", r.m_ptr); track_move_assigned((ref_tag*) this);
|
||||
ref &operator=(ref &&r) noexcept {
|
||||
print_move_assigned(this, "pointer", r.m_ptr);
|
||||
track_move_assigned((ref_tag *) this);
|
||||
|
||||
if (*this == r)
|
||||
if (*this == r) {
|
||||
return *this;
|
||||
if (m_ptr)
|
||||
}
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
m_ptr = r.m_ptr;
|
||||
r.m_ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Overwrite this reference with another reference
|
||||
ref& operator=(const ref& r) {
|
||||
print_copy_assigned(this, "pointer", r.m_ptr); track_copy_assigned((ref_tag*) this);
|
||||
|
||||
if (m_ptr == r.m_ptr)
|
||||
ref &operator=(const ref &r) {
|
||||
if (this == &r) {
|
||||
return *this;
|
||||
if (m_ptr)
|
||||
}
|
||||
print_copy_assigned(this, "pointer", r.m_ptr);
|
||||
track_copy_assigned((ref_tag *) this);
|
||||
|
||||
if (m_ptr == r.m_ptr) {
|
||||
return *this;
|
||||
}
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
m_ptr = r.m_ptr;
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Overwrite this reference with a pointer to another object
|
||||
ref& operator=(T *ptr) {
|
||||
print_values(this, "assigned pointer"); track_values((ref_tag*) this, "assigned pointer");
|
||||
ref &operator=(T *ptr) {
|
||||
print_values(this, "assigned pointer");
|
||||
track_values((ref_tag *) this, "assigned pointer");
|
||||
|
||||
if (m_ptr == ptr)
|
||||
if (m_ptr == ptr) {
|
||||
return *this;
|
||||
if (m_ptr)
|
||||
}
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->decRef();
|
||||
}
|
||||
m_ptr = ptr;
|
||||
if (m_ptr)
|
||||
if (m_ptr) {
|
||||
((Object *) m_ptr)->incRef();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -143,31 +172,32 @@ public:
|
||||
bool operator!=(const ref &r) const { return m_ptr != r.m_ptr; }
|
||||
|
||||
/// Compare this reference with a pointer
|
||||
bool operator==(const T* ptr) const { return m_ptr == ptr; }
|
||||
bool operator==(const T *ptr) const { return m_ptr == ptr; }
|
||||
|
||||
/// Compare this reference with a pointer
|
||||
bool operator!=(const T* ptr) const { return m_ptr != ptr; }
|
||||
bool operator!=(const T *ptr) const { return m_ptr != ptr; }
|
||||
|
||||
/// Access the object referenced by this reference
|
||||
T* operator->() { return m_ptr; }
|
||||
T *operator->() { return m_ptr; }
|
||||
|
||||
/// Access the object referenced by this reference
|
||||
const T* operator->() const { return m_ptr; }
|
||||
const T *operator->() const { return m_ptr; }
|
||||
|
||||
/// Return a C++ reference to the referenced object
|
||||
T& operator*() { return *m_ptr; }
|
||||
T &operator*() { return *m_ptr; }
|
||||
|
||||
/// Return a const C++ reference to the referenced object
|
||||
const T& operator*() const { return *m_ptr; }
|
||||
const T &operator*() const { return *m_ptr; }
|
||||
|
||||
/// Return a pointer to the referenced object
|
||||
operator T* () { return m_ptr; }
|
||||
explicit operator T *() { return m_ptr; }
|
||||
|
||||
/// Return a const pointer to the referenced object
|
||||
T* get_ptr() { return m_ptr; }
|
||||
T *get_ptr() { return m_ptr; }
|
||||
|
||||
/// Return a pointer to the referenced object
|
||||
const T* get_ptr() const { return m_ptr; }
|
||||
const T *get_ptr() const { return m_ptr; }
|
||||
|
||||
private:
|
||||
T *m_ptr;
|
||||
};
|
||||
|
@ -7,10 +7,14 @@
|
||||
BSD-style license that can be found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "pybind11_tests.h"
|
||||
#include "local_bindings.h"
|
||||
#include <pybind11/stl_bind.h>
|
||||
|
||||
#include "local_bindings.h"
|
||||
#include "pybind11_tests.h"
|
||||
#include "test_exceptions.h"
|
||||
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
m.doc() = "pybind11 cross-module test module";
|
||||
@ -25,17 +29,46 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
bind_local<ExternalType2>(m, "ExternalType2", py::module_local());
|
||||
|
||||
// test_exceptions.py
|
||||
m.def("raise_runtime_error", []() { PyErr_SetString(PyExc_RuntimeError, "My runtime error"); throw py::error_already_set(); });
|
||||
m.def("raise_value_error", []() { PyErr_SetString(PyExc_ValueError, "My value error"); throw py::error_already_set(); });
|
||||
py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException");
|
||||
m.def("raise_runtime_error", []() {
|
||||
PyErr_SetString(PyExc_RuntimeError, "My runtime error");
|
||||
throw py::error_already_set();
|
||||
});
|
||||
m.def("raise_value_error", []() {
|
||||
PyErr_SetString(PyExc_ValueError, "My value error");
|
||||
throw py::error_already_set();
|
||||
});
|
||||
m.def("throw_pybind_value_error", []() { throw py::value_error("pybind11 value error"); });
|
||||
m.def("throw_pybind_type_error", []() { throw py::type_error("pybind11 type error"); });
|
||||
m.def("throw_stop_iteration", []() { throw py::stop_iteration(); });
|
||||
m.def("throw_local_error", []() { throw LocalException("just local"); });
|
||||
m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); });
|
||||
py::register_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const shared_exception &e) {
|
||||
PyErr_SetString(PyExc_KeyError, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
// translate the local exception into a key error but only in this module
|
||||
py::register_local_exception_translator([](std::exception_ptr p) {
|
||||
try {
|
||||
if (p) {
|
||||
std::rethrow_exception(p);
|
||||
}
|
||||
} catch (const LocalException &e) {
|
||||
PyErr_SetString(PyExc_KeyError, e.what());
|
||||
}
|
||||
});
|
||||
|
||||
// test_local_bindings.py
|
||||
// Local to both:
|
||||
bind_local<LocalType, 1>(m, "LocalType", py::module_local())
|
||||
.def("get2", [](LocalType &t) { return t.i + 2; })
|
||||
;
|
||||
bind_local<LocalType, 1>(m, "LocalType", py::module_local()).def("get2", [](LocalType &t) {
|
||||
return t.i + 2;
|
||||
});
|
||||
|
||||
// Can only be called with our python type:
|
||||
m.def("local_value", [](LocalType &l) { return l.i; });
|
||||
@ -43,9 +76,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
// test_nonlocal_failure
|
||||
// This registration will fail (global registration when LocalFail is already registered
|
||||
// globally in the main test module):
|
||||
m.def("register_nonlocal", [m]() {
|
||||
bind_local<NonLocalType, 0>(m, "NonLocalType");
|
||||
});
|
||||
m.def("register_nonlocal", [m]() { bind_local<NonLocalType, 0>(m, "NonLocalType"); });
|
||||
|
||||
// test_stl_bind_local
|
||||
// stl_bind.h binders defaults to py::module_local if the types are local or converting:
|
||||
@ -55,27 +86,21 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
// test_stl_bind_global
|
||||
// and global if the type (or one of the types, for the map) is global (so these will fail,
|
||||
// assuming pybind11_tests is already loaded):
|
||||
m.def("register_nonlocal_vec", [m]() {
|
||||
py::bind_vector<NonLocalVec>(m, "NonLocalVec");
|
||||
});
|
||||
m.def("register_nonlocal_map", [m]() {
|
||||
py::bind_map<NonLocalMap>(m, "NonLocalMap");
|
||||
});
|
||||
m.def("register_nonlocal_vec", [m]() { py::bind_vector<NonLocalVec>(m, "NonLocalVec"); });
|
||||
m.def("register_nonlocal_map", [m]() { py::bind_map<NonLocalMap>(m, "NonLocalMap"); });
|
||||
// The default can, however, be overridden to global using `py::module_local()` or
|
||||
// `py::module_local(false)`.
|
||||
// Explicitly made local:
|
||||
py::bind_vector<NonLocalVec2>(m, "NonLocalVec2", py::module_local());
|
||||
// Explicitly made global (and so will fail to bind):
|
||||
m.def("register_nonlocal_map2", [m]() {
|
||||
py::bind_map<NonLocalMap2>(m, "NonLocalMap2", py::module_local(false));
|
||||
});
|
||||
m.def("register_nonlocal_map2",
|
||||
[m]() { py::bind_map<NonLocalMap2>(m, "NonLocalMap2", py::module_local(false)); });
|
||||
|
||||
// test_mixed_local_global
|
||||
// We try this both with the global type registered first and vice versa (the order shouldn't
|
||||
// matter).
|
||||
m.def("register_mixed_global_local", [m]() {
|
||||
bind_local<MixedGlobalLocal, 200>(m, "MixedGlobalLocal", py::module_local());
|
||||
});
|
||||
m.def("register_mixed_global_local",
|
||||
[m]() { bind_local<MixedGlobalLocal, 200>(m, "MixedGlobalLocal", py::module_local()); });
|
||||
m.def("register_mixed_local_global", [m]() {
|
||||
bind_local<MixedLocalGlobal, 2000>(m, "MixedLocalGlobal", py::module_local(false));
|
||||
});
|
||||
@ -83,25 +108,26 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); });
|
||||
|
||||
// test_internal_locals_differ
|
||||
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::registered_local_types_cpp(); });
|
||||
m.def("local_cpp_types_addr",
|
||||
[]() { return (uintptr_t) &py::detail::get_local_internals().registered_types_cpp; });
|
||||
|
||||
// test_stl_caster_vs_stl_bind
|
||||
py::bind_vector<std::vector<int>>(m, "VectorInt");
|
||||
|
||||
m.def("load_vector_via_binding", [](std::vector<int> &v) {
|
||||
return std::accumulate(v.begin(), v.end(), 0);
|
||||
});
|
||||
m.def("load_vector_via_binding",
|
||||
[](std::vector<int> &v) { return std::accumulate(v.begin(), v.end(), 0); });
|
||||
|
||||
// test_cross_module_calls
|
||||
m.def("return_self", [](LocalVec *v) { return v; });
|
||||
m.def("return_copy", [](const LocalVec &v) { return LocalVec(v); });
|
||||
|
||||
class Dog : public pets::Pet { public: Dog(std::string name) : Pet(name) {}; };
|
||||
py::class_<pets::Pet>(m, "Pet", py::module_local())
|
||||
.def("name", &pets::Pet::name);
|
||||
class Dog : public pets::Pet {
|
||||
public:
|
||||
explicit Dog(std::string name) : Pet(std::move(name)) {}
|
||||
};
|
||||
py::class_<pets::Pet>(m, "Pet", py::module_local()).def("name", &pets::Pet::name);
|
||||
// Binding for local extending class:
|
||||
py::class_<Dog, pets::Pet>(m, "Dog")
|
||||
.def(py::init<std::string>());
|
||||
py::class_<Dog, pets::Pet>(m, "Dog").def(py::init<std::string>());
|
||||
m.def("pet_name", [](pets::Pet &p) { return p.name(); });
|
||||
|
||||
py::class_<MixGL>(m, "MixGL", py::module_local()).def(py::init<int>());
|
||||
@ -118,6 +144,6 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
|
||||
// test_missing_header_message
|
||||
// The main module already includes stl.h, but we need to test the error message
|
||||
// which appears when this header is missing.
|
||||
m.def("missing_header_arg", [](std::vector<float>) { });
|
||||
m.def("missing_header_arg", [](const std::vector<float> &) {});
|
||||
m.def("missing_header_return", []() { return std::vector<float>(); });
|
||||
}
|
||||
|
54
3rdparty/pybind11/tests/pybind11_tests.cpp
vendored
54
3rdparty/pybind11/tests/pybind11_tests.cpp
vendored
@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include "pybind11_tests.h"
|
||||
|
||||
#include "constructor_stats.h"
|
||||
|
||||
#include <functional>
|
||||
@ -31,9 +32,7 @@ std::list<std::function<void(py::module_ &)>> &initializers() {
|
||||
return inits;
|
||||
}
|
||||
|
||||
test_initializer::test_initializer(Initializer init) {
|
||||
initializers().emplace_back(init);
|
||||
}
|
||||
test_initializer::test_initializer(Initializer init) { initializers().emplace_back(init); }
|
||||
|
||||
test_initializer::test_initializer(const char *submodule_name, Initializer init) {
|
||||
initializers().emplace_back([=](py::module_ &parent) {
|
||||
@ -51,26 +50,52 @@ void bind_ConstructorStats(py::module_ &m) {
|
||||
.def_readwrite("move_assignments", &ConstructorStats::move_assignments)
|
||||
.def_readwrite("copy_constructions", &ConstructorStats::copy_constructions)
|
||||
.def_readwrite("move_constructions", &ConstructorStats::move_constructions)
|
||||
.def_static("get", (ConstructorStats &(*)(py::object)) &ConstructorStats::get, py::return_value_policy::reference_internal)
|
||||
.def_static("get",
|
||||
(ConstructorStats & (*) (py::object)) & ConstructorStats::get,
|
||||
py::return_value_policy::reference_internal)
|
||||
|
||||
// Not exactly ConstructorStats, but related: expose the internal pybind number of registered instances
|
||||
// to allow instance cleanup checks (invokes a GC first)
|
||||
// Not exactly ConstructorStats, but related: expose the internal pybind number of
|
||||
// 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();
|
||||
})
|
||||
;
|
||||
});
|
||||
}
|
||||
|
||||
const char *cpp_std() {
|
||||
return
|
||||
#if defined(PYBIND11_CPP20)
|
||||
"C++20";
|
||||
#elif defined(PYBIND11_CPP17)
|
||||
"C++17";
|
||||
#elif defined(PYBIND11_CPP14)
|
||||
"C++14";
|
||||
#else
|
||||
"C++11";
|
||||
#endif
|
||||
}
|
||||
|
||||
PYBIND11_MODULE(pybind11_tests, m) {
|
||||
m.doc() = "pybind11 test module";
|
||||
|
||||
// Intentionally kept minimal to not create a maintenance chore
|
||||
// ("just enough" to be conclusive).
|
||||
#if defined(_MSC_FULL_VER)
|
||||
m.attr("compiler_info") = "MSVC " PYBIND11_TOSTRING(_MSC_FULL_VER);
|
||||
#elif defined(__VERSION__)
|
||||
m.attr("compiler_info") = __VERSION__;
|
||||
#else
|
||||
m.attr("compiler_info") = py::none();
|
||||
#endif
|
||||
m.attr("cpp_std") = cpp_std();
|
||||
m.attr("PYBIND11_INTERNALS_ID") = PYBIND11_INTERNALS_ID;
|
||||
|
||||
bind_ConstructorStats(m);
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
m.attr("debug_enabled") = true;
|
||||
#if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
|
||||
m.attr("detailed_error_messages_enabled") = true;
|
||||
#else
|
||||
m.attr("debug_enabled") = false;
|
||||
m.attr("detailed_error_messages_enabled") = false;
|
||||
#endif
|
||||
|
||||
py::class_<UserType>(m, "UserType", "A `py::class_` type for testing")
|
||||
@ -79,13 +104,14 @@ PYBIND11_MODULE(pybind11_tests, m) {
|
||||
.def("get_value", &UserType::value, "Get value using a method")
|
||||
.def("set_value", &UserType::set, "Set value using a method")
|
||||
.def_property("value", &UserType::value, &UserType::set, "Get/set value using a property")
|
||||
.def("__repr__", [](const UserType& u) { return "UserType({})"_s.format(u.value()); });
|
||||
.def("__repr__", [](const UserType &u) { return "UserType({})"_s.format(u.value()); });
|
||||
|
||||
py::class_<IncType, UserType>(m, "IncType")
|
||||
.def(py::init<>())
|
||||
.def(py::init<int>())
|
||||
.def("__repr__", [](const IncType& u) { return "IncType({})"_s.format(u.value()); });
|
||||
.def("__repr__", [](const IncType &u) { return "IncType({})"_s.format(u.value()); });
|
||||
|
||||
for (const auto &initializer : initializers())
|
||||
for (const auto &initializer : initializers()) {
|
||||
initializer(m);
|
||||
}
|
||||
}
|
||||
|
54
3rdparty/pybind11/tests/pybind11_tests.h
vendored
54
3rdparty/pybind11/tests/pybind11_tests.h
vendored
@ -1,10 +1,7 @@
|
||||
#pragma once
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
// We get some really long type names here which causes MSVC 2015 to emit warnings
|
||||
# pragma warning(disable: 4503) // warning C4503: decorated name length exceeded, name was truncated
|
||||
#endif
|
||||
#include <pybind11/eval.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace pybind11::literals;
|
||||
@ -13,24 +10,23 @@ class test_initializer {
|
||||
using Initializer = void (*)(py::module_ &);
|
||||
|
||||
public:
|
||||
test_initializer(Initializer init);
|
||||
explicit test_initializer(Initializer init);
|
||||
test_initializer(const char *submodule_name, Initializer init);
|
||||
};
|
||||
|
||||
#define TEST_SUBMODULE(name, variable) \
|
||||
void test_submodule_##name(py::module_ &); \
|
||||
test_initializer name(#name, test_submodule_##name); \
|
||||
void test_submodule_##name(py::module_ &variable)
|
||||
|
||||
#define TEST_SUBMODULE(name, variable) \
|
||||
void test_submodule_##name(py::module_ &); \
|
||||
test_initializer name(#name, test_submodule_##name); \
|
||||
void test_submodule_##name(py::module_ &(variable))
|
||||
|
||||
/// Dummy type which is not exported anywhere -- something to trigger a conversion error
|
||||
struct UnregisteredType { };
|
||||
struct UnregisteredType {};
|
||||
|
||||
/// A user-defined type which is exported and can be used by any test
|
||||
class UserType {
|
||||
public:
|
||||
UserType() = default;
|
||||
UserType(int i) : i(i) { }
|
||||
explicit UserType(int i) : i(i) {}
|
||||
|
||||
int value() const { return i; }
|
||||
void set(int set) { i = set; }
|
||||
@ -44,7 +40,7 @@ class IncType : public UserType {
|
||||
public:
|
||||
using UserType::UserType;
|
||||
IncType() = default;
|
||||
IncType(const IncType &other) : IncType(other.value() + 1) { }
|
||||
IncType(const IncType &other) : IncType(other.value() + 1) {}
|
||||
IncType(IncType &&) = delete;
|
||||
IncType &operator=(const IncType &) = delete;
|
||||
IncType &operator=(IncType &&) = delete;
|
||||
@ -56,16 +52,34 @@ union IntFloat {
|
||||
float f;
|
||||
};
|
||||
|
||||
/// 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).
|
||||
/// 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 {};
|
||||
PYBIND11_NAMESPACE_BEGIN(pybind11)
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
template<> class type_caster<RValueCaster> {
|
||||
template <>
|
||||
class type_caster<RValueCaster> {
|
||||
public:
|
||||
PYBIND11_TYPE_CASTER(RValueCaster, _("RValueCaster"));
|
||||
static handle cast(RValueCaster &&, return_value_policy, handle) { return py::str("rvalue").release(); }
|
||||
static handle cast(const RValueCaster &, return_value_policy, handle) { return py::str("lvalue").release(); }
|
||||
PYBIND11_TYPE_CASTER(RValueCaster, const_name("RValueCaster"));
|
||||
static handle cast(RValueCaster &&, return_value_policy, handle) {
|
||||
return py::str("rvalue").release();
|
||||
}
|
||||
static handle cast(const RValueCaster &, return_value_policy, handle) {
|
||||
return py::str("lvalue").release();
|
||||
}
|
||||
};
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(pybind11)
|
||||
|
||||
template <typename F>
|
||||
void ignoreOldStyleInitWarnings(F &&body) {
|
||||
py::exec(R"(
|
||||
message = "pybind11-bound class '.+' is using an old-style placement-new '(?:__init__|__setstate__)' which has been deprecated"
|
||||
|
||||
import warnings
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", message=message, category=FutureWarning)
|
||||
body()
|
||||
)",
|
||||
py::dict(py::arg("body") = py::cpp_function(body)));
|
||||
}
|
||||
|
13
3rdparty/pybind11/tests/pytest.ini
vendored
13
3rdparty/pybind11/tests/pytest.ini
vendored
@ -1,17 +1,20 @@
|
||||
[pytest]
|
||||
minversion = 3.1
|
||||
minversion = 3.10
|
||||
norecursedirs = test_* extra_*
|
||||
xfail_strict = True
|
||||
addopts =
|
||||
# show summary of skipped tests
|
||||
-rs
|
||||
# show summary of tests
|
||||
-ra
|
||||
# capture only Python print and C++ py::print, but not C output (low-level Python errors)
|
||||
--capture=sys
|
||||
# enable all warnings
|
||||
-Wa
|
||||
# Show local info when a failure occurs
|
||||
--showlocals
|
||||
log_cli_level = info
|
||||
filterwarnings =
|
||||
# make warnings into errors but ignore certain third-party extension issues
|
||||
error
|
||||
# somehow, some DeprecationWarnings do not get turned into errors
|
||||
always::DeprecationWarning
|
||||
# importing scipy submodules on some version of Python
|
||||
ignore::ImportWarning
|
||||
# bogus numpy ABI warning (see numpy/#432)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user