mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
chore: drop Python 3.5 (#3719)
* chore: drop Python 3.5 support * chore: more fstrings with flynt's help * ci: drop Python 3.5 * chore: bump dependency versions * docs: touch up py::args * tests: remove deprecation warning * Ban smartquotes * Very minor tweaks (by-product of reviewing PR #3719). Co-authored-by: Aaron Gokaslan <skylion.aaron@gmail.com> Co-authored-by: Ralf W. Grosse-Kunstleve <rwgk@google.com>
This commit is contained in:
parent
1a432b426f
commit
522c59ceb2
11
.github/CONTRIBUTING.md
vendored
11
.github/CONTRIBUTING.md
vendored
@ -93,11 +93,10 @@ cmake --build build -j4
|
|||||||
|
|
||||||
Tips:
|
Tips:
|
||||||
|
|
||||||
* You can use `virtualenv` (from PyPI) instead of `venv` (which is Python 3
|
* You can use `virtualenv` (faster, from PyPI) instead of `venv`.
|
||||||
only).
|
|
||||||
* You can select any name for your environment folder; if it contains "env" it
|
* You can select any name for your environment folder; if it contains "env" it
|
||||||
will be ignored by git.
|
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+
|
* 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`.
|
* In classic mode, you may need to set `-DPYTHON_EXECUTABLE=/path/to/python`.
|
||||||
FindPython uses `-DPython_ROOT_DIR=/path/to` or
|
FindPython uses `-DPython_ROOT_DIR=/path/to` or
|
||||||
@ -105,7 +104,7 @@ Tips:
|
|||||||
|
|
||||||
### Configuration options
|
### 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, in the `CMakeCache.txt` file, so they are remembered for each
|
||||||
build directory. Two selections are special - the generator, given with `-G`,
|
build directory. Two selections are special - the generator, given with `-G`,
|
||||||
and the compiler, which is selected based on environment variables `CXX` and
|
and the compiler, which is selected based on environment variables `CXX` and
|
||||||
@ -115,7 +114,7 @@ after the initial run.
|
|||||||
The valid options are:
|
The valid options are:
|
||||||
|
|
||||||
* `-DCMAKE_BUILD_TYPE`: Release, Debug, MinSizeRel, RelWithDebInfo
|
* `-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
|
classic, deprecated, custom FindPythonLibs
|
||||||
* `-DPYBIND11_NOPYTHON=ON`: Disable all Python searching (disables tests)
|
* `-DPYBIND11_NOPYTHON=ON`: Disable all Python searching (disables tests)
|
||||||
* `-DBUILD_TESTING=ON`: Enable the tests
|
* `-DBUILD_TESTING=ON`: Enable the tests
|
||||||
@ -257,7 +256,7 @@ The report is sent to stderr; you can pipe it into a file if you wish.
|
|||||||
### Build recipes
|
### Build recipes
|
||||||
|
|
||||||
This builds with the Intel compiler (assuming it is in your path, along with a
|
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
|
```bash
|
||||||
python3 -m venv venv
|
python3 -m venv venv
|
||||||
|
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@ -15,6 +15,8 @@ concurrency:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
PIP_ONLY_BINARY: numpy
|
PIP_ONLY_BINARY: numpy
|
||||||
|
FORCE_COLOR: 3
|
||||||
|
PYTEST_TIMEOUT: 300
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# This is the "main" test suite, which tests a large number of different
|
# This is the "main" test suite, which tests a large number of different
|
||||||
@ -25,7 +27,6 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
runs-on: [ubuntu-latest, windows-2022, macos-latest]
|
runs-on: [ubuntu-latest, windows-2022, macos-latest]
|
||||||
python:
|
python:
|
||||||
- '3.5'
|
|
||||||
- '3.6'
|
- '3.6'
|
||||||
- '3.9'
|
- '3.9'
|
||||||
- '3.10'
|
- '3.10'
|
||||||
@ -167,7 +168,7 @@ jobs:
|
|||||||
# setuptools
|
# setuptools
|
||||||
- name: Setuptools helpers test
|
- name: Setuptools helpers test
|
||||||
run: pytest tests/extra_setuptools
|
run: pytest tests/extra_setuptools
|
||||||
if: "!(matrix.python == '3.5' && matrix.runs-on == 'windows-2022')"
|
if: "!(matrix.runs-on == 'windows-2022')"
|
||||||
|
|
||||||
|
|
||||||
deadsnakes:
|
deadsnakes:
|
||||||
@ -624,9 +625,9 @@ jobs:
|
|||||||
|
|
||||||
# This tests an "install" with the CMake tools
|
# This tests an "install" with the CMake tools
|
||||||
install-classic:
|
install-classic:
|
||||||
name: "🐍 3.5 • Debian • x86 • Install"
|
name: "🐍 3.7 • Debian • x86 • Install"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container: i386/debian:stretch
|
container: i386/debian:buster
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v1
|
- uses: actions/checkout@v1
|
||||||
@ -635,7 +636,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y git make cmake g++ libeigen3-dev python3-dev python3-pip
|
apt-get install -y git make cmake g++ libeigen3-dev python3-dev python3-pip
|
||||||
pip3 install "pytest==3.1.*"
|
pip3 install "pytest==6.*"
|
||||||
|
|
||||||
- name: Configure for install
|
- name: Configure for install
|
||||||
run: >
|
run: >
|
||||||
@ -704,12 +705,10 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python:
|
python:
|
||||||
- 3.5
|
|
||||||
- 3.6
|
- 3.6
|
||||||
- 3.7
|
- 3.7
|
||||||
- 3.8
|
- 3.8
|
||||||
- 3.9
|
- 3.9
|
||||||
- pypy-3.6
|
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- python: 3.9
|
- python: 3.9
|
||||||
@ -810,7 +809,7 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
python:
|
python:
|
||||||
- 3.5
|
- 3.6
|
||||||
- 3.7
|
- 3.7
|
||||||
std:
|
std:
|
||||||
- 14
|
- 14
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
repos:
|
repos:
|
||||||
# Standard hooks
|
# Standard hooks
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.1.0
|
rev: "v4.1.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- id: check-case-conflict
|
- id: check-case-conflict
|
||||||
@ -32,26 +32,26 @@ repos:
|
|||||||
|
|
||||||
# Upgrade old Python syntax
|
# Upgrade old Python syntax
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v2.31.0
|
rev: "v2.31.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py3-plus]
|
args: [--py36-plus]
|
||||||
|
|
||||||
# Nicely sort includes
|
# Nicely sort includes
|
||||||
- repo: https://github.com/PyCQA/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.10.1
|
rev: "5.10.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
|
|
||||||
# Black, the code formatter, natively supports pre-commit
|
# Black, the code formatter, natively supports pre-commit
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.1.0 # Keep in sync with blacken-docs
|
rev: "22.1.0" # Keep in sync with blacken-docs
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
||||||
# Also code format the docs
|
# Also code format the docs
|
||||||
- repo: https://github.com/asottile/blacken-docs
|
- repo: https://github.com/asottile/blacken-docs
|
||||||
rev: v1.12.1
|
rev: "v1.12.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: blacken-docs
|
- id: blacken-docs
|
||||||
additional_dependencies:
|
additional_dependencies:
|
||||||
@ -59,32 +59,37 @@ repos:
|
|||||||
|
|
||||||
# Changes tabs to spaces
|
# Changes tabs to spaces
|
||||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||||
rev: v1.1.11
|
rev: "v1.1.11"
|
||||||
hooks:
|
hooks:
|
||||||
- id: remove-tabs
|
- id: remove-tabs
|
||||||
|
|
||||||
|
- repo: https://github.com/sirosen/texthooks
|
||||||
|
rev: "0.2.2"
|
||||||
|
hooks:
|
||||||
|
- id: fix-ligatures
|
||||||
|
- id: fix-smartquotes
|
||||||
|
|
||||||
# Autoremoves unused imports
|
# Autoremoves unused imports
|
||||||
- repo: https://github.com/hadialqattan/pycln
|
- repo: https://github.com/hadialqattan/pycln
|
||||||
rev: v1.1.0
|
rev: "v1.1.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: pycln
|
- id: pycln
|
||||||
|
|
||||||
# Checking for common mistakes
|
# Checking for common mistakes
|
||||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||||
rev: v1.9.0
|
rev: "v1.9.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: python-check-blanket-noqa
|
- id: python-check-blanket-noqa
|
||||||
- id: python-check-blanket-type-ignore
|
- id: python-check-blanket-type-ignore
|
||||||
- id: python-no-log-warn
|
- id: python-no-log-warn
|
||||||
# Python 3.6
|
- id: python-use-type-annotations
|
||||||
# - id: python-use-type-annotations
|
|
||||||
- id: rst-backticks
|
- id: rst-backticks
|
||||||
- id: rst-directive-colons
|
- id: rst-directive-colons
|
||||||
- id: rst-inline-touching-normal
|
- id: rst-inline-touching-normal
|
||||||
|
|
||||||
# Flake8 also supports pre-commit natively (same author)
|
# Flake8 also supports pre-commit natively (same author)
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 4.0.1
|
rev: "4.0.1"
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
additional_dependencies: &flake8_dependencies
|
additional_dependencies: &flake8_dependencies
|
||||||
@ -94,14 +99,14 @@ repos:
|
|||||||
|
|
||||||
# Automatically remove noqa that are not used
|
# Automatically remove noqa that are not used
|
||||||
- repo: https://github.com/asottile/yesqa
|
- repo: https://github.com/asottile/yesqa
|
||||||
rev: v1.3.0
|
rev: "v1.3.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: yesqa
|
- id: yesqa
|
||||||
additional_dependencies: *flake8_dependencies
|
additional_dependencies: *flake8_dependencies
|
||||||
|
|
||||||
# CMake formatting
|
# CMake formatting
|
||||||
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
- repo: https://github.com/cheshirekow/cmake-format-precommit
|
||||||
rev: v0.6.13
|
rev: "v0.6.13"
|
||||||
hooks:
|
hooks:
|
||||||
- id: cmake-format
|
- id: cmake-format
|
||||||
additional_dependencies: [pyyaml]
|
additional_dependencies: [pyyaml]
|
||||||
@ -110,7 +115,7 @@ repos:
|
|||||||
|
|
||||||
# Check static types with mypy
|
# Check static types with mypy
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v0.931
|
rev: "v0.931"
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
args: [--show-error-codes]
|
args: [--show-error-codes]
|
||||||
@ -128,7 +133,7 @@ repos:
|
|||||||
|
|
||||||
# Check for spelling
|
# Check for spelling
|
||||||
- repo: https://github.com/codespell-project/codespell
|
- repo: https://github.com/codespell-project/codespell
|
||||||
rev: v2.1.0
|
rev: "v2.1.0"
|
||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
exclude: ".supp$"
|
exclude: ".supp$"
|
||||||
@ -136,7 +141,7 @@ repos:
|
|||||||
|
|
||||||
# Check for common shell mistakes
|
# Check for common shell mistakes
|
||||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||||
rev: v0.8.0.4
|
rev: "v0.8.0.4"
|
||||||
hooks:
|
hooks:
|
||||||
- id: shellcheck
|
- id: shellcheck
|
||||||
|
|
||||||
|
14
README.rst
14
README.rst
@ -32,9 +32,9 @@ this heavy machinery has become an excessively large and unnecessary
|
|||||||
dependency.
|
dependency.
|
||||||
|
|
||||||
Think of this library as a tiny self-contained version of Boost.Python
|
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
|
generation. Without comments, the core header files only require ~4K
|
||||||
lines of code and depend on Python (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
|
standard library. This compact implementation was possible thanks to
|
||||||
some of the new C++11 language features (specifically: tuples, lambda
|
some of the new C++11 language features (specifically: tuples, lambda
|
||||||
functions and variadic templates). Since its creation, this library has
|
functions and variadic templates). Since its creation, this library has
|
||||||
@ -78,8 +78,8 @@ Goodies
|
|||||||
In addition to the core functionality, pybind11 provides some extra
|
In addition to the core functionality, pybind11 provides some extra
|
||||||
goodies:
|
goodies:
|
||||||
|
|
||||||
- Python 3.5+, and PyPy3 7.3 are supported with an implementation-agnostic
|
- 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).
|
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
|
- It is possible to bind C++11 lambda functions with captured
|
||||||
variables. The lambda capture data is stored inside the resulting
|
variables. The lambda capture data is stored inside the resulting
|
||||||
@ -88,8 +88,8 @@ goodies:
|
|||||||
- pybind11 uses C++11 move constructors and move assignment operators
|
- pybind11 uses C++11 move constructors and move assignment operators
|
||||||
whenever possible to efficiently transfer custom data types.
|
whenever possible to efficiently transfer custom data types.
|
||||||
|
|
||||||
- It’s easy to expose the internal storage of custom data types through
|
- It's easy to expose the internal storage of custom data types through
|
||||||
Pythons’ buffer protocols. This is handy e.g. for fast conversion
|
Pythons' buffer protocols. This is handy e.g. for fast conversion
|
||||||
between C++ matrix classes like Eigen and NumPy without expensive
|
between C++ matrix classes like Eigen and NumPy without expensive
|
||||||
copy operations.
|
copy operations.
|
||||||
|
|
||||||
@ -119,7 +119,7 @@ goodies:
|
|||||||
Supported compilers
|
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)
|
newer)
|
||||||
2. GCC 4.8 or newer
|
2. GCC 4.8 or newer
|
||||||
3. Microsoft Visual Studio 2015 Update 3 or newer
|
3. Microsoft Visual Studio 2015 Update 3 or newer
|
||||||
|
@ -167,5 +167,4 @@ as arguments and return values, refer to the section on binding :ref:`classes`.
|
|||||||
+------------------------------------+---------------------------+-----------------------------------+
|
+------------------------------------+---------------------------+-----------------------------------+
|
||||||
|
|
||||||
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
.. [#] ``std::filesystem::path`` is converted to ``pathlib.Path`` and
|
||||||
``os.PathLike`` is converted to ``std::filesystem::path``, but this requires
|
``os.PathLike`` is converted to ``std::filesystem::path``.
|
||||||
Python 3.6 (for ``__fspath__`` support).
|
|
||||||
|
@ -372,7 +372,7 @@ like so:
|
|||||||
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:
|
argument in a function definition:
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
@ -395,19 +395,18 @@ argument annotations when registering the function:
|
|||||||
m.def("f", [](int a, int b) { /* ... */ },
|
m.def("f", [](int a, int b) { /* ... */ },
|
||||||
py::arg("a"), py::kw_only(), py::arg("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
|
.. versionadded:: 2.6
|
||||||
|
|
||||||
As of pybind11 2.9, a ``py::args`` argument implies that any following arguments
|
A ``py::args`` argument implies that any following arguments are keyword-only,
|
||||||
are keyword-only, as if ``py::kw_only()`` had been specified in the same
|
as if ``py::kw_only()`` had been specified in the same relative location of the
|
||||||
relative location of the argument list as the ``py::args`` argument. The
|
argument list as the ``py::args`` argument. The ``py::kw_only()`` may be
|
||||||
``py::kw_only()`` may be included to be explicit about this, but is not
|
included to be explicit about this, but is not required.
|
||||||
required. (Prior to 2.9 ``py::args`` may only occur at the end of the argument
|
|
||||||
list, or immediately before a ``py::kwargs`` argument at the end).
|
.. 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.
|
||||||
|
|
||||||
.. versionadded:: 2.9
|
|
||||||
|
|
||||||
Positional-only arguments
|
Positional-only arguments
|
||||||
=========================
|
=========================
|
||||||
|
@ -395,7 +395,7 @@ uses of ``py::array``:
|
|||||||
Ellipsis
|
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
|
slice multidimensional arrays. For instance, the following snippet extracts the
|
||||||
middle dimensions of a tensor with the first and last index set to zero.
|
middle dimensions of a tensor with the first and last index set to zero.
|
||||||
|
|
||||||
|
@ -11,20 +11,20 @@ def generate_dummy_code_pybind11(nclasses=10):
|
|||||||
bindings = ""
|
bindings = ""
|
||||||
|
|
||||||
for cl in range(nclasses):
|
for cl in range(nclasses):
|
||||||
decl += "class cl%03i;\n" % cl
|
decl += f"class cl{cl:03};\n"
|
||||||
decl += "\n"
|
decl += "\n"
|
||||||
|
|
||||||
for cl in range(nclasses):
|
for cl in range(nclasses):
|
||||||
decl += "class cl%03i {\n" % cl
|
decl += f"class {cl:03} {{\n"
|
||||||
decl += "public:\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):
|
for fn in range(nfns):
|
||||||
ret = random.randint(0, nclasses - 1)
|
ret = random.randint(0, nclasses - 1)
|
||||||
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
||||||
decl += " cl%03i *fn_%03i(" % (ret, fn)
|
decl += f" cl{ret:03} *fn_{fn:03}("
|
||||||
decl += ", ".join("cl%03i *" % p for p in params)
|
decl += ", ".join(f"cl{p:03} *" for p in params)
|
||||||
decl += ");\n"
|
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"
|
decl += "};\n\n"
|
||||||
bindings += " ;\n"
|
bindings += " ;\n"
|
||||||
|
|
||||||
@ -42,23 +42,20 @@ def generate_dummy_code_boost(nclasses=10):
|
|||||||
bindings = ""
|
bindings = ""
|
||||||
|
|
||||||
for cl in range(nclasses):
|
for cl in range(nclasses):
|
||||||
decl += "class cl%03i;\n" % cl
|
decl += f"class cl{cl:03};\n"
|
||||||
decl += "\n"
|
decl += "\n"
|
||||||
|
|
||||||
for cl in range(nclasses):
|
for cl in range(nclasses):
|
||||||
decl += "class cl%03i {\n" % cl
|
decl += "class cl%03i {\n" % cl
|
||||||
decl += "public:\n"
|
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):
|
for fn in range(nfns):
|
||||||
ret = random.randint(0, nclasses - 1)
|
ret = random.randint(0, nclasses - 1)
|
||||||
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
params = [random.randint(0, nclasses - 1) for i in range(nargs)]
|
||||||
decl += " cl%03i *fn_%03i(" % (ret, fn)
|
decl += f" cl{ret:03} *fn_{fn:03}("
|
||||||
decl += ", ".join("cl%03i *" % p for p in params)
|
decl += ", ".join(f"cl{p:03} *" for p in params)
|
||||||
decl += ");\n"
|
decl += ");\n"
|
||||||
bindings += (
|
bindings += f' .def("fn_{fn:03}", &cl{cl:03}::fn_{fn:03}, py::return_value_policy<py::manage_new_object>())\n'
|
||||||
' .def("fn_%03i", &cl%03i::fn_%03i, py::return_value_policy<py::manage_new_object>())\n'
|
|
||||||
% (fn, cl, fn)
|
|
||||||
)
|
|
||||||
decl += "};\n\n"
|
decl += "};\n\n"
|
||||||
bindings += " ;\n"
|
bindings += " ;\n"
|
||||||
|
|
||||||
|
@ -800,7 +800,7 @@ Packaging / building improvements:
|
|||||||
`#2338 <https://github.com/pybind/pybind11/pull/2338>`_ and
|
`#2338 <https://github.com/pybind/pybind11/pull/2338>`_ and
|
||||||
`#2370 <https://github.com/pybind/pybind11/pull/2370>`_
|
`#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``.
|
replaces ``PYBIND11_CPP_STANDARD``.
|
||||||
|
|
||||||
* Generated config file is now portable to different Python/compiler/CMake
|
* Generated config file is now portable to different Python/compiler/CMake
|
||||||
|
@ -417,10 +417,10 @@ existing targets instead:
|
|||||||
|
|
||||||
.. code-block:: cmake
|
.. code-block:: cmake
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.15...3.19)
|
cmake_minimum_required(VERSION 3.15...3.22)
|
||||||
project(example LANGUAGES CXX)
|
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)
|
find_package(pybind11 CONFIG REQUIRED)
|
||||||
# or add_subdirectory(pybind11)
|
# or add_subdirectory(pybind11)
|
||||||
|
|
||||||
@ -433,9 +433,8 @@ algorithms from the CMake invocation, with ``-DPYBIND11_FINDPYTHON=ON``.
|
|||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
|
|
||||||
If you use FindPython2 and FindPython3 to dual-target Python, use the
|
If you use FindPython to multi-target Python versions, use the individual
|
||||||
individual targets listed below, and avoid targets that directly include
|
targets listed below, and avoid targets that directly include Python parts.
|
||||||
Python parts.
|
|
||||||
|
|
||||||
There are `many ways to hint or force a discovery of a specific Python
|
There are `many ways to hint or force a discovery of a specific Python
|
||||||
installation <https://cmake.org/cmake/help/latest/module/FindPython.html>`_),
|
installation <https://cmake.org/cmake/help/latest/module/FindPython.html>`_),
|
||||||
|
@ -344,9 +344,9 @@ def generate_doxygen_xml(app):
|
|||||||
subprocess.call(["doxygen", "--version"])
|
subprocess.call(["doxygen", "--version"])
|
||||||
retcode = subprocess.call(["doxygen"], cwd=app.confdir)
|
retcode = subprocess.call(["doxygen"], cwd=app.confdir)
|
||||||
if retcode < 0:
|
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:
|
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):
|
def prepare(app):
|
||||||
|
@ -145,7 +145,7 @@ using C++14 template metaprogramming.
|
|||||||
|
|
||||||
.. _`faq:hidden_visibility`:
|
.. _`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
|
This error typically indicates that you are compiling without the required
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
breathe==4.31.0
|
breathe==4.32.0
|
||||||
sphinx==3.5.4
|
sphinx==4.4.0
|
||||||
sphinx_rtd_theme==1.0.0
|
sphinx_rtd_theme==1.0.0
|
||||||
sphinxcontrib-moderncmakedomain==3.19
|
sphinxcontrib-moderncmakedomain==3.21.4
|
||||||
sphinxcontrib-svg2pdfconverter==1.1.1
|
sphinxcontrib-svg2pdfconverter==1.2.0
|
||||||
|
@ -524,7 +524,7 @@ include a declaration of the form:
|
|||||||
|
|
||||||
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
|
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.
|
but it's completely redundant.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1585,7 +1585,7 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
|
|||||||
template <typename Derived>
|
template <typename Derived>
|
||||||
template <return_value_policy policy, typename... Args>
|
template <return_value_policy policy, typename... Args>
|
||||||
object object_api<Derived>::operator()(Args &&...args) const {
|
object object_api<Derived>::operator()(Args &&...args) const {
|
||||||
#if !defined(NDEBUG) && PY_VERSION_HEX >= 0x03060000
|
#ifndef NDEBUG
|
||||||
if (!PyGILState_Check()) {
|
if (!PyGILState_Check()) {
|
||||||
pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure.");
|
pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure.");
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,6 @@
|
|||||||
#include <datetime.h>
|
#include <datetime.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
@ -211,8 +211,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
#if PY_VERSION_HEX < 0x030500f0
|
#if PY_VERSION_HEX < 0x03060000
|
||||||
# error "PYTHON 2 IS NO LONGER SUPPORTED. pybind11 v2.9 was the last to support Python 2."
|
# error "PYTHON < 3.6 IS UNSUPPORTED. pybind11 v2.9 was the last to support Python 2 and 3.5."
|
||||||
#endif
|
#endif
|
||||||
#include <frameobject.h>
|
#include <frameobject.h>
|
||||||
#include <pythread.h>
|
#include <pythread.h>
|
||||||
@ -301,15 +301,6 @@
|
|||||||
extern "C" PYBIND11_MAYBE_UNUSED PYBIND11_EXPORT PyObject *PyInit_##name(); \
|
extern "C" PYBIND11_MAYBE_UNUSED PYBIND11_EXPORT PyObject *PyInit_##name(); \
|
||||||
extern "C" PYBIND11_EXPORT PyObject *PyInit_##name()
|
extern "C" PYBIND11_EXPORT PyObject *PyInit_##name()
|
||||||
|
|
||||||
#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200
|
|
||||||
extern "C" {
|
|
||||||
struct _Py_atomic_address {
|
|
||||||
void *value;
|
|
||||||
};
|
|
||||||
PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code
|
#define PYBIND11_TRY_NEXT_OVERLOAD ((PyObject *) 1) // special failure return code
|
||||||
#define PYBIND11_STRINGIFY(x) #x
|
#define PYBIND11_STRINGIFY(x) #x
|
||||||
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
|
#define PYBIND11_TOSTRING(x) PYBIND11_STRINGIFY(x)
|
||||||
@ -438,7 +429,7 @@ enum class return_value_policy : uint8_t {
|
|||||||
|
|
||||||
/** Reference an existing object (i.e. do not create a new copy) and take
|
/** Reference an existing object (i.e. do not create a new copy) and take
|
||||||
ownership. Python will call the destructor and delete operator when the
|
ownership. Python will call the destructor and delete operator when the
|
||||||
object’s reference count reaches zero. Undefined behavior ensues when
|
object's reference count reaches zero. Undefined behavior ensues when
|
||||||
the C++ side does the same.. */
|
the C++ side does the same.. */
|
||||||
take_ownership,
|
take_ownership,
|
||||||
|
|
||||||
@ -454,7 +445,7 @@ enum class return_value_policy : uint8_t {
|
|||||||
move,
|
move,
|
||||||
|
|
||||||
/** Reference an existing object, but do not take ownership. The C++ side
|
/** Reference an existing object, but do not take ownership. The C++ side
|
||||||
is responsible for managing the object’s lifetime and deallocating it
|
is responsible for managing the object's lifetime and deallocating it
|
||||||
when it is no longer used. Warning: undefined behavior will ensue when
|
when it is no longer used. Warning: undefined behavior will ensue when
|
||||||
the C++ side deletes an object that is still referenced and used by
|
the C++ side deletes an object that is still referenced and used by
|
||||||
Python. */
|
Python. */
|
||||||
@ -463,7 +454,7 @@ enum class return_value_policy : uint8_t {
|
|||||||
/** This policy only applies to methods and properties. It references the
|
/** This policy only applies to methods and properties. It references the
|
||||||
object without taking ownership similar to the above
|
object without taking ownership similar to the above
|
||||||
return_value_policy::reference policy. In contrast to that policy, the
|
return_value_policy::reference policy. In contrast to that policy, the
|
||||||
function or property’s implicit this argument (called the parent) is
|
function or property's implicit this argument (called the parent) is
|
||||||
considered to be the the owner of the return value (the child).
|
considered to be the the owner of the return value (the child).
|
||||||
pybind11 then couples the lifetime of the parent to the child via a
|
pybind11 then couples the lifetime of the parent to the child via a
|
||||||
reference relationship that ensures that the parent cannot be garbage
|
reference relationship that ensures that the parent cannot be garbage
|
||||||
|
@ -439,10 +439,11 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
|
|||||||
// instance_registered)
|
// instance_registered)
|
||||||
|
|
||||||
// Allocate space for flags, values, and holders, and initialize it to 0 (flags and values,
|
// Allocate space for flags, values, and holders, and initialize it to 0 (flags and values,
|
||||||
// in particular, need to be 0). Use Python's memory allocation functions: in Python 3.6
|
// in particular, need to be 0). Use Python's memory allocation
|
||||||
// they default to using pymalloc, which is designed to be efficient for small allocations
|
// functions: Python is using pymalloc, which is designed to be
|
||||||
// like the one we're doing here; in earlier versions (and for larger allocations) they are
|
// efficient for small allocations like the one we're doing here;
|
||||||
// just wrappers around malloc.
|
// for larger allocations they are just wrappers around malloc.
|
||||||
|
// TODO: is this still true for pure Python 3.6?
|
||||||
nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
|
nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
|
||||||
if (!nonsimple.values_and_holders) {
|
if (!nonsimple.values_and_holders) {
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
@ -538,8 +539,6 @@ PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_i
|
|||||||
inline PyThreadState *get_thread_state_unchecked() {
|
inline PyThreadState *get_thread_state_unchecked() {
|
||||||
#if defined(PYPY_VERSION)
|
#if defined(PYPY_VERSION)
|
||||||
return PyThreadState_GET();
|
return PyThreadState_GET();
|
||||||
#elif PY_VERSION_HEX < 0x03050200
|
|
||||||
return (PyThreadState *) _PyThreadState_Current.value;
|
|
||||||
#else
|
#else
|
||||||
return _PyThreadState_UncheckedGet();
|
return _PyThreadState_UncheckedGet();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1213,7 +1213,7 @@ public:
|
|||||||
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
|
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
|
||||||
}
|
}
|
||||||
|
|
||||||
using module_def = PyModuleDef;
|
using module_def = PyModuleDef; // TODO: Can this be removed (it was needed only for Python 2)?
|
||||||
|
|
||||||
/** \rst
|
/** \rst
|
||||||
Create a new top-level module that can be used as the main module of a C extension.
|
Create a new top-level module that can be used as the main module of a C extension.
|
||||||
@ -1241,8 +1241,8 @@ public:
|
|||||||
pybind11_fail("Internal error in module_::create_extension_module()");
|
pybind11_fail("Internal error in module_::create_extension_module()");
|
||||||
}
|
}
|
||||||
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when
|
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when
|
||||||
// returned from PyInit_...
|
// returned from PyInit_...
|
||||||
// For Python 2, reinterpret_borrow is correct.
|
// For Python 2, reinterpret_borrow was correct.
|
||||||
return reinterpret_borrow<module_>(m);
|
return reinterpret_borrow<module_>(m);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -13,8 +13,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifdef __has_include
|
#ifdef __has_include
|
||||||
# if defined(PYBIND11_CPP17) && __has_include(<filesystem>) && \
|
# if defined(PYBIND11_CPP17) && __has_include(<filesystem>)
|
||||||
PY_VERSION_HEX >= 0x03060000
|
|
||||||
# include <filesystem>
|
# include <filesystem>
|
||||||
# define PYBIND11_HAS_FILESYSTEM 1
|
# define PYBIND11_HAS_FILESYSTEM 1
|
||||||
# endif
|
# endif
|
||||||
|
@ -2,7 +2,7 @@ import nox
|
|||||||
|
|
||||||
nox.options.sessions = ["lint", "tests", "tests_packaging"]
|
nox.options.sessions = ["lint", "tests", "tests_packaging"]
|
||||||
|
|
||||||
PYTHON_VERSIONS = ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
|
PYTHON_VERSIONS = ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||||
|
|
||||||
|
|
||||||
@nox.session(reuse_venv=True)
|
@nox.session(reuse_venv=True)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info < (3, 5):
|
if sys.version_info < (3, 6):
|
||||||
msg = "pybind11 does not support Python < 3.5. 2.9 was the last release supporting older Pythons."
|
msg = "pybind11 does not support Python < 3.6. 2.9 was the last release supporting Python 2.7 and 3.5."
|
||||||
raise ImportError(msg)
|
raise ImportError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ class Pybind11Extension(_Extension): # type: ignore[misc]
|
|||||||
current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2])
|
current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2])
|
||||||
desired_macos = (10, 9) if level < 17 else (10, 14)
|
desired_macos = (10, 9) if level < 17 else (10, 14)
|
||||||
macos_string = ".".join(str(x) for x in min(current_macos, desired_macos))
|
macos_string = ".".join(str(x) for x in min(current_macos, desired_macos))
|
||||||
macosx_min = "-mmacosx-version-min={}".format(macos_string)
|
macosx_min = f"-mmacosx-version-min={macos_string}"
|
||||||
cflags += [macosx_min]
|
cflags += [macosx_min]
|
||||||
ldflags += [macosx_min]
|
ldflags += [macosx_min]
|
||||||
|
|
||||||
@ -322,9 +322,9 @@ def intree_extensions(
|
|||||||
|
|
||||||
if not exts:
|
if not exts:
|
||||||
msg = (
|
msg = (
|
||||||
"path {path} is not a child of any of the directories listed "
|
f"path {path} is not a child of any of the directories listed "
|
||||||
"in 'package_dir' ({package_dir})"
|
f"in 'package_dir' ({package_dir})"
|
||||||
).format(path=path, package_dir=package_dir)
|
)
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
|
||||||
return exts
|
return exts
|
||||||
@ -419,7 +419,7 @@ class ParallelCompile:
|
|||||||
self.default = default
|
self.default = default
|
||||||
self.max = max
|
self.max = max
|
||||||
self.needs_recompile = needs_recompile
|
self.needs_recompile = needs_recompile
|
||||||
self._old = [] # type: List[CCompilerMethod]
|
self._old: List[CCompilerMethod] = []
|
||||||
|
|
||||||
def function(self) -> CCompilerMethod:
|
def function(self) -> CCompilerMethod:
|
||||||
"""
|
"""
|
||||||
|
16
setup.cfg
16
setup.cfg
@ -14,7 +14,6 @@ classifiers =
|
|||||||
Topic :: Utilities
|
Topic :: Utilities
|
||||||
Programming Language :: C++
|
Programming Language :: C++
|
||||||
Programming Language :: Python :: 3 :: Only
|
Programming Language :: Python :: 3 :: Only
|
||||||
Programming Language :: Python :: 3.5
|
|
||||||
Programming Language :: Python :: 3.6
|
Programming Language :: Python :: 3.6
|
||||||
Programming Language :: Python :: 3.7
|
Programming Language :: Python :: 3.7
|
||||||
Programming Language :: Python :: 3.8
|
Programming Language :: Python :: 3.8
|
||||||
@ -38,7 +37,7 @@ project_urls =
|
|||||||
Chat = https://gitter.im/pybind/Lobby
|
Chat = https://gitter.im/pybind/Lobby
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
python_requires = >=3.5
|
python_requires = >=3.6
|
||||||
zip_safe = False
|
zip_safe = False
|
||||||
|
|
||||||
|
|
||||||
@ -46,14 +45,5 @@ zip_safe = False
|
|||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
show_source = True
|
show_source = True
|
||||||
exclude = .git, __pycache__, build, dist, docs, tools, venv
|
exclude = .git, __pycache__, build, dist, docs, tools, venv
|
||||||
ignore =
|
extend-ignore = E203, E722, B950
|
||||||
# required for pretty matrix formatting: multiple spaces after `,` and `[`
|
select = C,E,F,N,W,B,B9
|
||||||
E201, E241, W504,
|
|
||||||
# camelcase 'cPickle' imported as lowercase 'pickle'
|
|
||||||
N813
|
|
||||||
# Black conflict
|
|
||||||
W503, E203
|
|
||||||
|
|
||||||
|
|
||||||
[tool:pytest]
|
|
||||||
timeout = 300
|
|
||||||
|
20
setup.py
20
setup.py
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# Setup script for PyPI; use CMakeFile.txt to build extension modules
|
# Setup script for PyPI; use CMakeFile.txt to build extension modules
|
||||||
|
|
||||||
@ -41,12 +41,10 @@ def build_expected_version_hex(matches: Dict[str, str]) -> str:
|
|||||||
serial = int(level_serial[len(level) :])
|
serial = int(level_serial[len(level) :])
|
||||||
break
|
break
|
||||||
if serial is None:
|
if serial is None:
|
||||||
msg = 'Invalid PYBIND11_VERSION_PATCH: "{}"'.format(patch_level_serial)
|
msg = f'Invalid PYBIND11_VERSION_PATCH: "{patch_level_serial}"'
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
version_hex_str = "{:02x}{:02x}{:02x}{}{:x}".format(
|
version_hex_str = f"{major:02x}{minor:02x}{patch:02x}{level[:1]}{serial:x}"
|
||||||
major, minor, patch, level[:1], serial
|
return f"0x{version_hex_str.upper()}"
|
||||||
)
|
|
||||||
return "0x{}".format(version_hex_str.upper())
|
|
||||||
|
|
||||||
|
|
||||||
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
|
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
|
||||||
@ -66,7 +64,7 @@ to_src = (
|
|||||||
|
|
||||||
|
|
||||||
# Read the listed version
|
# Read the listed version
|
||||||
loc = {} # type: Dict[str, str]
|
loc: Dict[str, str] = {}
|
||||||
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
|
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
|
||||||
exec(code, loc)
|
exec(code, loc)
|
||||||
version = loc["__version__"]
|
version = loc["__version__"]
|
||||||
@ -75,17 +73,13 @@ version = loc["__version__"]
|
|||||||
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
|
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
|
||||||
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
|
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
|
||||||
if version != cpp_version:
|
if version != cpp_version:
|
||||||
msg = "Python version {} does not match C++ version {}!".format(
|
msg = f"Python version {version} does not match C++ version {cpp_version}!"
|
||||||
version, cpp_version
|
|
||||||
)
|
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
version_hex = matches.get("HEX", "MISSING")
|
version_hex = matches.get("HEX", "MISSING")
|
||||||
exp_version_hex = build_expected_version_hex(matches)
|
exp_version_hex = build_expected_version_hex(matches)
|
||||||
if version_hex != exp_version_hex:
|
if version_hex != exp_version_hex:
|
||||||
msg = "PYBIND11_VERSION_HEX {} does not match expected value {}!".format(
|
msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
|
||||||
version_hex, exp_version_hex
|
|
||||||
)
|
|
||||||
raise RuntimeError(msg)
|
raise RuntimeError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
@ -145,9 +145,9 @@ def test_build_sdist(monkeypatch, tmpdir):
|
|||||||
contents = f.read().decode("utf8")
|
contents = f.read().decode("utf8")
|
||||||
assert 'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")' in contents
|
assert 'set(pybind11_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/include")' in contents
|
||||||
|
|
||||||
files = {"pybind11/{}".format(n) for n in all_files}
|
files = {f"pybind11/{n}" for n in all_files}
|
||||||
files |= sdist_files
|
files |= sdist_files
|
||||||
files |= {"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/entry_points.txt")
|
||||||
files.add("pybind11.egg-info/requires.txt")
|
files.add("pybind11.egg-info/requires.txt")
|
||||||
assert simpler == files
|
assert simpler == files
|
||||||
@ -200,9 +200,9 @@ def test_build_global_dist(monkeypatch, tmpdir):
|
|||||||
) as f:
|
) as f:
|
||||||
pyproject_toml = f.read()
|
pyproject_toml = f.read()
|
||||||
|
|
||||||
files = {"pybind11/{}".format(n) for n in all_files}
|
files = {f"pybind11/{n}" for n in all_files}
|
||||||
files |= sdist_files
|
files |= sdist_files
|
||||||
files |= {"pybind11_global{}".format(n) for n in local_sdist_files}
|
files |= {f"pybind11_global{n}" for n in local_sdist_files}
|
||||||
assert simpler == files
|
assert simpler == files
|
||||||
|
|
||||||
with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f:
|
with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f:
|
||||||
@ -227,7 +227,7 @@ def tests_build_wheel(monkeypatch, tmpdir):
|
|||||||
|
|
||||||
(wheel,) = tmpdir.visit("*.whl")
|
(wheel,) = tmpdir.visit("*.whl")
|
||||||
|
|
||||||
files = {"pybind11/{}".format(n) for n in all_files}
|
files = {f"pybind11/{n}" for n in all_files}
|
||||||
files |= {
|
files |= {
|
||||||
"dist-info/LICENSE",
|
"dist-info/LICENSE",
|
||||||
"dist-info/METADATA",
|
"dist-info/METADATA",
|
||||||
@ -241,9 +241,7 @@ def tests_build_wheel(monkeypatch, tmpdir):
|
|||||||
names = z.namelist()
|
names = z.namelist()
|
||||||
|
|
||||||
trimmed = {n for n in names if "dist-info" not in n}
|
trimmed = {n for n in names if "dist-info" not in n}
|
||||||
trimmed |= {
|
trimmed |= {f"dist-info/{n.split('/', 1)[-1]}" for n in names if "dist-info" in n}
|
||||||
"dist-info/{}".format(n.split("/", 1)[-1]) for n in names if "dist-info" in n
|
|
||||||
}
|
|
||||||
assert files == trimmed
|
assert files == trimmed
|
||||||
|
|
||||||
|
|
||||||
@ -257,8 +255,8 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
|
|||||||
|
|
||||||
(wheel,) = tmpdir.visit("*.whl")
|
(wheel,) = tmpdir.visit("*.whl")
|
||||||
|
|
||||||
files = {"data/data/{}".format(n) for n in src_files}
|
files = {f"data/data/{n}" for n in src_files}
|
||||||
files |= {"data/headers/{}".format(n[8:]) for n in headers}
|
files |= {f"data/headers/{n[8:]}" for n in headers}
|
||||||
files |= {
|
files |= {
|
||||||
"dist-info/LICENSE",
|
"dist-info/LICENSE",
|
||||||
"dist-info/METADATA",
|
"dist-info/METADATA",
|
||||||
|
@ -18,7 +18,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
|||||||
|
|
||||||
(tmpdir / "setup.py").write_text(
|
(tmpdir / "setup.py").write_text(
|
||||||
dedent(
|
dedent(
|
||||||
"""\
|
f"""\
|
||||||
import sys
|
import sys
|
||||||
sys.path.append({MAIN_DIR!r})
|
sys.path.append({MAIN_DIR!r})
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
|||||||
ext_modules=ext_modules,
|
ext_modules=ext_modules,
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
).format(MAIN_DIR=MAIN_DIR, std=std, parallel=parallel),
|
),
|
||||||
encoding="ascii",
|
encoding="ascii",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
[pytest]
|
[pytest]
|
||||||
minversion = 3.1
|
minversion = 3.10
|
||||||
norecursedirs = test_* extra_*
|
norecursedirs = test_* extra_*
|
||||||
xfail_strict = True
|
xfail_strict = True
|
||||||
addopts =
|
addopts =
|
||||||
# show summary of skipped tests
|
# show summary of tests
|
||||||
-rs
|
-ra
|
||||||
# capture only Python print and C++ py::print, but not C output (low-level Python errors)
|
# capture only Python print and C++ py::print, but not C output (low-level Python errors)
|
||||||
--capture=sys
|
--capture=sys
|
||||||
|
# Show local info when a failure occurs
|
||||||
|
--showlocals
|
||||||
|
log_cli_level = info
|
||||||
filterwarnings =
|
filterwarnings =
|
||||||
# make warnings into errors but ignore certain third-party extension issues
|
# make warnings into errors but ignore certain third-party extension issues
|
||||||
error
|
error
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
numpy==1.16.6; python_version<"3.6" and sys_platform!="win32" and platform_python_implementation!="PyPy"
|
numpy==1.21.5; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
|
||||||
numpy==1.19.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.6"
|
|
||||||
numpy==1.20.0; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
|
|
||||||
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
|
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
|
||||||
numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.11"
|
numpy==1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10"
|
||||||
py @ git+https://github.com/pytest-dev/py; python_version>="3.11"
|
numpy==1.22.2; platform_python_implementation!="PyPy" and python_version>="3.10" and python_version<"3.11"
|
||||||
pytest==4.6.9; python_version<"3.5"
|
pytest==7.0.0
|
||||||
pytest==6.1.2; python_version=="3.5"
|
|
||||||
pytest==6.2.4; python_version>="3.6"
|
|
||||||
pytest-timeout
|
pytest-timeout
|
||||||
scipy==1.2.3; platform_python_implementation!="PyPy" and python_version<"3.6"
|
scipy==1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10"
|
||||||
scipy==1.5.4; platform_python_implementation!="PyPy" and python_version>="3.6" and python_version<"3.10"
|
scipy==1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10"
|
||||||
|
@ -50,7 +50,7 @@ def test_single_char_arguments():
|
|||||||
"""Tests failures for passing invalid inputs to char-accepting functions"""
|
"""Tests failures for passing invalid inputs to char-accepting functions"""
|
||||||
|
|
||||||
def toobig_message(r):
|
def toobig_message(r):
|
||||||
return "Character code point not in range({:#x})".format(r)
|
return f"Character code point not in range({r:#x})"
|
||||||
|
|
||||||
toolong_message = "Expected a character, but multi-character string found"
|
toolong_message = "Expected a character, but multi-character string found"
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ def test_callbacks():
|
|||||||
return "func2", a, b, c, d
|
return "func2", a, b, c, d
|
||||||
|
|
||||||
def func3(a):
|
def func3(a):
|
||||||
return "func3({})".format(a)
|
return f"func3({a})"
|
||||||
|
|
||||||
assert m.test_callback1(func1) == "func1"
|
assert m.test_callback1(func1) == "func1"
|
||||||
assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5)
|
assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5)
|
||||||
@ -188,14 +188,8 @@ def test_callback_num_times():
|
|||||||
if not rep:
|
if not rep:
|
||||||
print()
|
print()
|
||||||
print(
|
print(
|
||||||
"callback_num_times: {:d} million / {:.3f} seconds = {:.3f} million / second".format(
|
f"callback_num_times: {num_millions:d} million / {td:.3f} seconds = {rate:.3f} million / second"
|
||||||
num_millions, td, rate
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if len(rates) > 1:
|
if len(rates) > 1:
|
||||||
print("Min Mean Max")
|
print("Min Mean Max")
|
||||||
print(
|
print(f"{min(rates):6.3f} {sum(rates) / len(rates):6.3f} {max(rates):6.3f}")
|
||||||
"{:6.3f} {:6.3f} {:6.3f}".format(
|
|
||||||
min(rates), sum(rates) / len(rates), max(rates)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
@ -100,7 +100,7 @@ SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
|
|||||||
)
|
)
|
||||||
def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
|
def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
|
||||||
if tz is not None:
|
if tz is not None:
|
||||||
monkeypatch.setenv("TZ", "/usr/share/zoneinfo/{}".format(tz))
|
monkeypatch.setenv("TZ", f"/usr/share/zoneinfo/{tz}")
|
||||||
|
|
||||||
# Roundtrip the time
|
# Roundtrip the time
|
||||||
datetime2 = m.test_chrono2(time1)
|
datetime2 = m.test_chrono2(time1)
|
||||||
|
@ -5,4 +5,4 @@ import test_cmake_build
|
|||||||
assert isinstance(__file__, str) # Test this is properly set
|
assert isinstance(__file__, str) # Test this is properly set
|
||||||
|
|
||||||
assert test_cmake_build.add(1, 2) == 3
|
assert test_cmake_build.add(1, 2) == 3
|
||||||
print("{} imports, runs, and adds: 1 + 2 = 3".format(sys.argv[1]))
|
print(f"{sys.argv[1]} imports, runs, and adds: 1 + 2 = 3")
|
||||||
|
@ -221,9 +221,7 @@ def test_nonunit_stride_to_python():
|
|||||||
assert np.all(m.diagonal(ref) == ref.diagonal())
|
assert np.all(m.diagonal(ref) == ref.diagonal())
|
||||||
assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
|
assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
|
||||||
for i in range(-5, 7):
|
for i in range(-5, 7):
|
||||||
assert np.all(
|
assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), f"m.diagonal_n({i})"
|
||||||
m.diagonal_n(ref, i) == ref.diagonal(i)
|
|
||||||
), "m.diagonal_n({})".format(i)
|
|
||||||
|
|
||||||
assert np.all(m.block(ref, 2, 1, 3, 3) == ref[2:5, 1:4])
|
assert np.all(m.block(ref, 2, 1, 3, 3) == ref[2:5, 1:4])
|
||||||
assert np.all(m.block(ref, 1, 4, 4, 2) == ref[1:, 4:])
|
assert np.all(m.block(ref, 1, 4, 4, 2) == ref[1:, 4:])
|
||||||
@ -236,7 +234,7 @@ def test_eigen_ref_to_python():
|
|||||||
mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
|
mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
|
||||||
assert np.all(
|
assert np.all(
|
||||||
mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
|
mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
|
||||||
), "cholesky{}".format(i)
|
), f"cholesky{i}"
|
||||||
|
|
||||||
|
|
||||||
def assign_both(a1, a2, r, c, v):
|
def assign_both(a1, a2, r, c, v):
|
||||||
|
@ -88,7 +88,7 @@ def test_python_call_in_catch():
|
|||||||
def ignore_pytest_unraisable_warning(f):
|
def ignore_pytest_unraisable_warning(f):
|
||||||
unraisable = "PytestUnraisableExceptionWarning"
|
unraisable = "PytestUnraisableExceptionWarning"
|
||||||
if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
|
if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
|
||||||
dec = pytest.mark.filterwarnings("ignore::pytest.{}".format(unraisable))
|
dec = pytest.mark.filterwarnings(f"ignore::pytest.{unraisable}")
|
||||||
return dec(f)
|
return dec(f)
|
||||||
else:
|
else:
|
||||||
return f
|
return f
|
||||||
|
@ -18,9 +18,7 @@ def test_dtypes():
|
|||||||
assert check.numpy == check.pybind11, check
|
assert check.numpy == check.pybind11, check
|
||||||
if check.numpy.num != check.pybind11.num:
|
if check.numpy.num != check.pybind11.num:
|
||||||
print(
|
print(
|
||||||
"NOTE: typenum mismatch for {}: {} != {}".format(
|
f"NOTE: typenum mismatch for {check}: {check.numpy.num} != {check.pybind11.num}"
|
||||||
check, check.numpy.num, check.pybind11.num
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -116,9 +114,7 @@ def test_at_fail(arr, dim):
|
|||||||
for func in m.at_t, m.mutate_at_t:
|
for func in m.at_t, m.mutate_at_t:
|
||||||
with pytest.raises(IndexError) as excinfo:
|
with pytest.raises(IndexError) as excinfo:
|
||||||
func(arr, *([0] * dim))
|
func(arr, *([0] * dim))
|
||||||
assert str(excinfo.value) == "index dimension mismatch: {} (ndim = 2)".format(
|
assert str(excinfo.value) == f"index dimension mismatch: {dim} (ndim = 2)"
|
||||||
dim
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_at(arr):
|
def test_at(arr):
|
||||||
@ -192,8 +188,6 @@ def test_make_empty_shaped_array():
|
|||||||
|
|
||||||
def test_wrap():
|
def test_wrap():
|
||||||
def assert_references(a, b, base=None):
|
def assert_references(a, b, base=None):
|
||||||
from distutils.version import LooseVersion
|
|
||||||
|
|
||||||
if base is None:
|
if base is None:
|
||||||
base = a
|
base = a
|
||||||
assert a is not b
|
assert a is not b
|
||||||
@ -204,7 +198,8 @@ def test_wrap():
|
|||||||
assert a.flags.f_contiguous == b.flags.f_contiguous
|
assert a.flags.f_contiguous == b.flags.f_contiguous
|
||||||
assert a.flags.writeable == b.flags.writeable
|
assert a.flags.writeable == b.flags.writeable
|
||||||
assert a.flags.aligned == b.flags.aligned
|
assert a.flags.aligned == b.flags.aligned
|
||||||
if LooseVersion(np.__version__) >= LooseVersion("1.14.0"):
|
# 1.13 supported Python 3.6
|
||||||
|
if tuple(int(x) for x in np.__version__.split(".")[:2]) >= (1, 14):
|
||||||
assert a.flags.writebackifcopy == b.flags.writebackifcopy
|
assert a.flags.writebackifcopy == b.flags.writebackifcopy
|
||||||
else:
|
else:
|
||||||
assert a.flags.updateifcopy == b.flags.updateifcopy
|
assert a.flags.updateifcopy == b.flags.updateifcopy
|
||||||
|
@ -14,7 +14,7 @@ def simple_dtype():
|
|||||||
return np.dtype(
|
return np.dtype(
|
||||||
{
|
{
|
||||||
"names": ["bool_", "uint_", "float_", "ldbl_"],
|
"names": ["bool_", "uint_", "float_", "ldbl_"],
|
||||||
"formats": ["?", "u4", "f4", "f{}".format(ld.itemsize)],
|
"formats": ["?", "u4", "f4", f"f{ld.itemsize}"],
|
||||||
"offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)],
|
"offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -125,7 +125,7 @@ def test_dtype(simple_dtype):
|
|||||||
assert [x.replace(" ", "") for x in m.print_dtypes()] == [
|
assert [x.replace(" ", "") for x in m.print_dtypes()] == [
|
||||||
simple_dtype_fmt(),
|
simple_dtype_fmt(),
|
||||||
packed_dtype_fmt(),
|
packed_dtype_fmt(),
|
||||||
"[('a',{}),('b',{})]".format(simple_dtype_fmt(), packed_dtype_fmt()),
|
f"[('a',{simple_dtype_fmt()}),('b',{packed_dtype_fmt()})]",
|
||||||
partial_dtype_fmt(),
|
partial_dtype_fmt(),
|
||||||
partial_nested_fmt(),
|
partial_nested_fmt(),
|
||||||
"[('a','S3'),('b','S3')]",
|
"[('a','S3'),('b','S3')]",
|
||||||
|
@ -12,7 +12,7 @@ def test_string_list():
|
|||||||
assert lst.back() == "Element 2"
|
assert lst.back() == "Element 2"
|
||||||
|
|
||||||
for i, k in enumerate(lst, start=1):
|
for i, k in enumerate(lst, start=1):
|
||||||
assert k == "Element {}".format(i)
|
assert k == f"Element {i}"
|
||||||
lst.pop_back()
|
lst.pop_back()
|
||||||
assert m.print_opaque_list(lst) == "Opaque list: [Element 1]"
|
assert m.print_opaque_list(lst) == "Opaque list: [Element 1]"
|
||||||
|
|
||||||
|
@ -305,8 +305,8 @@ def test_non_converting_constructors():
|
|||||||
for move in [True, False]:
|
for move in [True, False]:
|
||||||
with pytest.raises(TypeError) as excinfo:
|
with pytest.raises(TypeError) as excinfo:
|
||||||
m.nonconverting_constructor(t, v, move)
|
m.nonconverting_constructor(t, v, move)
|
||||||
expected_error = "Object of type '{}' is not an instance of '{}'".format(
|
expected_error = (
|
||||||
type(v).__name__, t
|
f"Object of type '{type(v).__name__}' is not an instance of '{t}'"
|
||||||
)
|
)
|
||||||
assert str(excinfo.value) == expected_error
|
assert str(excinfo.value) == expected_error
|
||||||
|
|
||||||
|
@ -1,20 +1,10 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
from pytest import approx
|
||||||
|
|
||||||
from pybind11_tests import ConstructorStats
|
from pybind11_tests import ConstructorStats
|
||||||
from pybind11_tests import sequences_and_iterators as m
|
from pybind11_tests import sequences_and_iterators as m
|
||||||
|
|
||||||
|
|
||||||
def isclose(a, b, rel_tol=1e-05, abs_tol=0.0):
|
|
||||||
"""Like math.isclose() from Python 3.5"""
|
|
||||||
return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
|
|
||||||
|
|
||||||
|
|
||||||
def allclose(a_list, b_list, rel_tol=1e-05, abs_tol=0.0):
|
|
||||||
return all(
|
|
||||||
isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) for a, b in zip(a_list, b_list)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_slice_constructors():
|
def test_slice_constructors():
|
||||||
assert m.make_forward_slice_size_t() == slice(0, -1, 1)
|
assert m.make_forward_slice_size_t() == slice(0, -1, 1)
|
||||||
assert m.make_reversed_slice_object() == slice(None, None, -1)
|
assert m.make_reversed_slice_object() == slice(None, None, -1)
|
||||||
@ -117,7 +107,8 @@ def test_sequence():
|
|||||||
assert 12.34 not in s
|
assert 12.34 not in s
|
||||||
s[0], s[3] = 12.34, 56.78
|
s[0], s[3] = 12.34, 56.78
|
||||||
assert 12.34 in s
|
assert 12.34 in s
|
||||||
assert isclose(s[0], 12.34) and isclose(s[3], 56.78)
|
assert s[0] == approx(12.34, rel=1e-05)
|
||||||
|
assert s[3] == approx(56.78, rel=1e-05)
|
||||||
|
|
||||||
rev = reversed(s)
|
rev = reversed(s)
|
||||||
assert cstats.values() == ["of size", "5"]
|
assert cstats.values() == ["of size", "5"]
|
||||||
@ -132,14 +123,14 @@ def test_sequence():
|
|||||||
assert cstats.values() == ["of size", "0"]
|
assert cstats.values() == ["of size", "0"]
|
||||||
|
|
||||||
expected = [0, 56.78, 0, 0, 12.34]
|
expected = [0, 56.78, 0, 0, 12.34]
|
||||||
assert allclose(rev, expected)
|
assert rev == approx(expected, rel=1e-05)
|
||||||
assert allclose(rev2, expected)
|
assert rev2 == approx(expected, rel=1e-05)
|
||||||
assert rev == rev2
|
assert rev == rev2
|
||||||
|
|
||||||
rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
|
rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
|
||||||
assert cstats.values() == ["of size", "3", "from std::vector"]
|
assert cstats.values() == ["of size", "3", "from std::vector"]
|
||||||
|
|
||||||
assert allclose(rev, [2, 56.78, 2, 0, 2])
|
assert rev == approx([2, 56.78, 2, 0, 2], rel=1e-05)
|
||||||
|
|
||||||
assert cstats.alive() == 4
|
assert cstats.alive() == 4
|
||||||
del it
|
del it
|
||||||
|
@ -15,7 +15,7 @@ def test_smart_ptr(capture):
|
|||||||
m.print_object_2(o)
|
m.print_object_2(o)
|
||||||
m.print_object_3(o)
|
m.print_object_3(o)
|
||||||
m.print_object_4(o)
|
m.print_object_4(o)
|
||||||
assert capture == "MyObject1[{i}]\n".format(i=i) * 4
|
assert capture == f"MyObject1[{i}]\n" * 4
|
||||||
|
|
||||||
for i, o in enumerate(
|
for i, o in enumerate(
|
||||||
[m.make_myobject1_1(), m.make_myobject1_2(), m.MyObject1(6), 7], start=4
|
[m.make_myobject1_1(), m.make_myobject1_2(), m.MyObject1(6), 7], start=4
|
||||||
@ -33,13 +33,11 @@ def test_smart_ptr(capture):
|
|||||||
m.print_myobject1_4(o)
|
m.print_myobject1_4(o)
|
||||||
|
|
||||||
times = 4 if isinstance(o, int) else 8
|
times = 4 if isinstance(o, int) else 8
|
||||||
assert capture == "MyObject1[{i}]\n".format(i=i) * times
|
assert capture == f"MyObject1[{i}]\n" * times
|
||||||
|
|
||||||
cstats = ConstructorStats.get(m.MyObject1)
|
cstats = ConstructorStats.get(m.MyObject1)
|
||||||
assert cstats.alive() == 0
|
assert cstats.alive() == 0
|
||||||
expected_values = ["MyObject1[{}]".format(i) for i in range(1, 7)] + [
|
expected_values = [f"MyObject1[{i}]" for i in range(1, 7)] + ["MyObject1[7]"] * 4
|
||||||
"MyObject1[7]"
|
|
||||||
] * 4
|
|
||||||
assert cstats.values() == expected_values
|
assert cstats.values() == expected_values
|
||||||
assert cstats.default_constructions == 0
|
assert cstats.default_constructions == 0
|
||||||
assert cstats.copy_constructions == 0
|
assert cstats.copy_constructions == 0
|
||||||
@ -57,7 +55,7 @@ def test_smart_ptr(capture):
|
|||||||
m.print_myobject2_2(o)
|
m.print_myobject2_2(o)
|
||||||
m.print_myobject2_3(o)
|
m.print_myobject2_3(o)
|
||||||
m.print_myobject2_4(o)
|
m.print_myobject2_4(o)
|
||||||
assert capture == "MyObject2[{i}]\n".format(i=i) * 4
|
assert capture == f"MyObject2[{i}]\n" * 4
|
||||||
|
|
||||||
cstats = ConstructorStats.get(m.MyObject2)
|
cstats = ConstructorStats.get(m.MyObject2)
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
@ -80,7 +78,7 @@ def test_smart_ptr(capture):
|
|||||||
m.print_myobject3_2(o)
|
m.print_myobject3_2(o)
|
||||||
m.print_myobject3_3(o)
|
m.print_myobject3_3(o)
|
||||||
m.print_myobject3_4(o)
|
m.print_myobject3_4(o)
|
||||||
assert capture == "MyObject3[{i}]\n".format(i=i) * 4
|
assert capture == f"MyObject3[{i}]\n" * 4
|
||||||
|
|
||||||
cstats = ConstructorStats.get(m.MyObject3)
|
cstats = ConstructorStats.get(m.MyObject3)
|
||||||
assert cstats.alive() == 1
|
assert cstats.alive() == 1
|
||||||
|
@ -13,7 +13,7 @@ def test_override(capture, msg):
|
|||||||
self.data = "Hello world"
|
self.data = "Hello world"
|
||||||
|
|
||||||
def run(self, value):
|
def run(self, value):
|
||||||
print("ExtendedExampleVirt::run(%i), calling parent.." % value)
|
print(f"ExtendedExampleVirt::run({value}), calling parent..")
|
||||||
return super().run(value + 1)
|
return super().run(value + 1)
|
||||||
|
|
||||||
def run_bool(self):
|
def run_bool(self):
|
||||||
@ -24,7 +24,7 @@ def test_override(capture, msg):
|
|||||||
return "override1"
|
return "override1"
|
||||||
|
|
||||||
def pure_virtual(self):
|
def pure_virtual(self):
|
||||||
print("ExtendedExampleVirt::pure_virtual(): %s" % self.data)
|
print(f"ExtendedExampleVirt::pure_virtual(): {self.data}")
|
||||||
|
|
||||||
class ExtendedExampleVirt2(ExtendedExampleVirt):
|
class ExtendedExampleVirt2(ExtendedExampleVirt):
|
||||||
def __init__(self, state):
|
def __init__(self, state):
|
||||||
|
@ -92,7 +92,7 @@ endif()
|
|||||||
|
|
||||||
# Use the Python interpreter to find the libs.
|
# Use the Python interpreter to find the libs.
|
||||||
if(NOT PythonLibsNew_FIND_VERSION)
|
if(NOT PythonLibsNew_FIND_VERSION)
|
||||||
set(PythonLibsNew_FIND_VERSION "3.5")
|
set(PythonLibsNew_FIND_VERSION "3.6")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}
|
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}
|
||||||
|
@ -13,7 +13,7 @@ lib = sys.argv[1]
|
|||||||
save = sys.argv[2]
|
save = sys.argv[2]
|
||||||
|
|
||||||
if not os.path.exists(lib):
|
if not os.path.exists(lib):
|
||||||
sys.exit("Error: requested file ({}) does not exist".format(lib))
|
sys.exit(f"Error: requested file ({lib}) does not exist")
|
||||||
|
|
||||||
libsize = os.path.getsize(lib)
|
libsize = os.path.getsize(lib)
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ if os.path.exists(save):
|
|||||||
if change == 0:
|
if change == 0:
|
||||||
print(" (no change)")
|
print(" (no change)")
|
||||||
else:
|
else:
|
||||||
print(" (change of {:+} bytes = {:+.2%})".format(change, change / oldsize))
|
print(f" (change of {change:+} bytes = {change / oldsize:+.2%})")
|
||||||
else:
|
else:
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ Using ``find_package`` with version info is not recommended except for release v
|
|||||||
.. code-block:: cmake
|
.. code-block:: cmake
|
||||||
|
|
||||||
find_package(pybind11 CONFIG)
|
find_package(pybind11 CONFIG)
|
||||||
find_package(pybind11 2.0 EXACT CONFIG REQUIRED)
|
find_package(pybind11 2.9 EXACT CONFIG REQUIRED)
|
||||||
|
|
||||||
#]=============================================================================]
|
#]=============================================================================]
|
||||||
@PACKAGE_INIT@
|
@PACKAGE_INIT@
|
||||||
|
@ -32,7 +32,7 @@ if(NOT Python_FOUND AND NOT Python3_FOUND)
|
|||||||
set(Python_ROOT_DIR "$ENV{pythonLocation}")
|
set(Python_ROOT_DIR "$ENV{pythonLocation}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Python 3.5 REQUIRED COMPONENTS Interpreter Development ${_pybind11_quiet})
|
find_package(Python 3.6 REQUIRED COMPONENTS Interpreter Development ${_pybind11_quiet})
|
||||||
|
|
||||||
# If we are in submodule mode, export the Python targets to global targets.
|
# If we are in submodule mode, export the Python targets to global targets.
|
||||||
# If this behavior is not desired, FindPython _before_ pybind11.
|
# If this behavior is not desired, FindPython _before_ pybind11.
|
||||||
|
@ -43,7 +43,7 @@ endif()
|
|||||||
|
|
||||||
# A user can set versions manually too
|
# A user can set versions manually too
|
||||||
set(Python_ADDITIONAL_VERSIONS
|
set(Python_ADDITIONAL_VERSIONS
|
||||||
"3.11;3.10;3.9;3.8;3.7;3.6;3.5"
|
"3.11;3.10;3.9;3.8;3.7;3.6"
|
||||||
CACHE INTERNAL "")
|
CACHE INTERNAL "")
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Setup script for pybind11-global (in the sdist or in tools/setup_global.py in the repository)
|
# Setup script for pybind11-global (in the sdist or in tools/setup_global.py in the repository)
|
||||||
# This package is targeted for easy use from CMake.
|
# This package is targeted for easy use from CMake.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# Setup script (in the sdist or in tools/setup_main.py in the repository)
|
# Setup script (in the sdist or in tools/setup_main.py in the repository)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user