mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-21 20:55: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:
|
||||
|
||||
* 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
|
||||
@ -105,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
|
||||
@ -115,7 +114,7 @@ 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
|
||||
@ -257,7 +256,7 @@ 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
|
||||
|
15
.github/workflows/ci.yml
vendored
15
.github/workflows/ci.yml
vendored
@ -15,6 +15,8 @@ concurrency:
|
||||
|
||||
env:
|
||||
PIP_ONLY_BINARY: numpy
|
||||
FORCE_COLOR: 3
|
||||
PYTEST_TIMEOUT: 300
|
||||
|
||||
jobs:
|
||||
# This is the "main" test suite, which tests a large number of different
|
||||
@ -25,7 +27,6 @@ jobs:
|
||||
matrix:
|
||||
runs-on: [ubuntu-latest, windows-2022, macos-latest]
|
||||
python:
|
||||
- '3.5'
|
||||
- '3.6'
|
||||
- '3.9'
|
||||
- '3.10'
|
||||
@ -167,7 +168,7 @@ jobs:
|
||||
# setuptools
|
||||
- name: Setuptools helpers test
|
||||
run: pytest tests/extra_setuptools
|
||||
if: "!(matrix.python == '3.5' && matrix.runs-on == 'windows-2022')"
|
||||
if: "!(matrix.runs-on == 'windows-2022')"
|
||||
|
||||
|
||||
deadsnakes:
|
||||
@ -624,9 +625,9 @@ jobs:
|
||||
|
||||
# This tests an "install" with the CMake tools
|
||||
install-classic:
|
||||
name: "🐍 3.5 • Debian • x86 • Install"
|
||||
name: "🐍 3.7 • Debian • x86 • Install"
|
||||
runs-on: ubuntu-latest
|
||||
container: i386/debian:stretch
|
||||
container: i386/debian:buster
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
@ -635,7 +636,7 @@ jobs:
|
||||
run: |
|
||||
apt-get update
|
||||
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
|
||||
run: >
|
||||
@ -704,12 +705,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python:
|
||||
- 3.5
|
||||
- 3.6
|
||||
- 3.7
|
||||
- 3.8
|
||||
- 3.9
|
||||
- pypy-3.6
|
||||
|
||||
include:
|
||||
- python: 3.9
|
||||
@ -810,7 +809,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python:
|
||||
- 3.5
|
||||
- 3.6
|
||||
- 3.7
|
||||
std:
|
||||
- 14
|
||||
|
@ -15,7 +15,7 @@
|
||||
repos:
|
||||
# Standard hooks
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.1.0
|
||||
rev: "v4.1.0"
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
@ -32,26 +32,26 @@ repos:
|
||||
|
||||
# Upgrade old Python syntax
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.31.0
|
||||
rev: "v2.31.0"
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py3-plus]
|
||||
args: [--py36-plus]
|
||||
|
||||
# Nicely sort includes
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.10.1
|
||||
rev: "5.10.1"
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
# Black, the code formatter, natively supports pre-commit
|
||||
- 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:
|
||||
- id: black
|
||||
|
||||
# Also code format the docs
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: v1.12.1
|
||||
rev: "v1.12.1"
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies:
|
||||
@ -59,32 +59,37 @@ repos:
|
||||
|
||||
# Changes tabs to spaces
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.1.11
|
||||
rev: "v1.1.11"
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
|
||||
- repo: https://github.com/sirosen/texthooks
|
||||
rev: "0.2.2"
|
||||
hooks:
|
||||
- id: fix-ligatures
|
||||
- id: fix-smartquotes
|
||||
|
||||
# Autoremoves unused imports
|
||||
- repo: https://github.com/hadialqattan/pycln
|
||||
rev: v1.1.0
|
||||
rev: "v1.1.0"
|
||||
hooks:
|
||||
- id: pycln
|
||||
|
||||
# Checking for common mistakes
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.9.0
|
||||
rev: "v1.9.0"
|
||||
hooks:
|
||||
- id: python-check-blanket-noqa
|
||||
- id: python-check-blanket-type-ignore
|
||||
- id: python-no-log-warn
|
||||
# Python 3.6
|
||||
# - id: python-use-type-annotations
|
||||
- id: python-use-type-annotations
|
||||
- id: rst-backticks
|
||||
- id: rst-directive-colons
|
||||
- id: rst-inline-touching-normal
|
||||
|
||||
# Flake8 also supports pre-commit natively (same author)
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 4.0.1
|
||||
rev: "4.0.1"
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies: &flake8_dependencies
|
||||
@ -94,14 +99,14 @@ repos:
|
||||
|
||||
# Automatically remove noqa that are not used
|
||||
- repo: https://github.com/asottile/yesqa
|
||||
rev: v1.3.0
|
||||
rev: "v1.3.0"
|
||||
hooks:
|
||||
- id: yesqa
|
||||
additional_dependencies: *flake8_dependencies
|
||||
|
||||
# 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]
|
||||
@ -110,7 +115,7 @@ repos:
|
||||
|
||||
# Check static types with mypy
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.931
|
||||
rev: "v0.931"
|
||||
hooks:
|
||||
- id: mypy
|
||||
args: [--show-error-codes]
|
||||
@ -128,7 +133,7 @@ repos:
|
||||
|
||||
# Check for spelling
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.1.0
|
||||
rev: "v2.1.0"
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: ".supp$"
|
||||
@ -136,7 +141,7 @@ repos:
|
||||
|
||||
# Check for common shell mistakes
|
||||
- repo: https://github.com/shellcheck-py/shellcheck-py
|
||||
rev: v0.8.0.4
|
||||
rev: "v0.8.0.4"
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
||||
|
14
README.rst
14
README.rst
@ -32,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 (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
|
||||
@ -78,8 +78,8 @@ Goodies
|
||||
In addition to the core functionality, pybind11 provides some extra
|
||||
goodies:
|
||||
|
||||
- Python 3.5+, and PyPy3 7.3 are supported with an implementation-agnostic
|
||||
interface (pybind11 2.9 was the last version to support Python 2).
|
||||
- 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
|
||||
@ -88,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.
|
||||
|
||||
@ -119,7 +119,7 @@ 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
|
||||
|
@ -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
|
||||
``os.PathLike`` is converted to ``std::filesystem::path``, but this requires
|
||||
Python 3.6 (for ``__fspath__`` support).
|
||||
``os.PathLike`` is converted to ``std::filesystem::path``.
|
||||
|
@ -372,7 +372,7 @@ like so:
|
||||
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
|
||||
@ -395,19 +395,18 @@ 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
|
||||
|
||||
As of pybind11 2.9, a ``py::args`` argument implies that any following arguments
|
||||
are keyword-only, as if ``py::kw_only()`` had been specified in the same
|
||||
relative location of the argument list as the ``py::args`` argument. The
|
||||
``py::kw_only()`` may be included to be explicit about this, but is not
|
||||
required. (Prior to 2.9 ``py::args`` may only occur at the end of the argument
|
||||
list, or immediately before a ``py::kwargs`` argument at the end).
|
||||
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.
|
||||
|
||||
.. versionadded:: 2.9
|
||||
|
||||
Positional-only arguments
|
||||
=========================
|
||||
|
@ -395,7 +395,7 @@ 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.
|
||||
|
||||
|
@ -11,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"
|
||||
|
||||
@ -42,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"
|
||||
|
||||
|
@ -800,7 +800,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
|
||||
|
@ -417,10 +417,10 @@ existing targets instead:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
cmake_minimum_required(VERSION 3.15...3.19)
|
||||
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)
|
||||
|
||||
@ -433,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>`_),
|
||||
|
@ -344,9 +344,9 @@ 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):
|
||||
|
@ -145,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
|
||||
|
@ -1,5 +1,5 @@
|
||||
breathe==4.31.0
|
||||
sphinx==3.5.4
|
||||
breathe==4.32.0
|
||||
sphinx==4.4.0
|
||||
sphinx_rtd_theme==1.0.0
|
||||
sphinxcontrib-moderncmakedomain==3.19
|
||||
sphinxcontrib-svg2pdfconverter==1.1.1
|
||||
sphinxcontrib-moderncmakedomain==3.21.4
|
||||
sphinxcontrib-svg2pdfconverter==1.2.0
|
||||
|
@ -524,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.
|
||||
|
||||
|
||||
|
@ -1585,7 +1585,7 @@ unpacking_collector<policy> collect_arguments(Args &&...args) {
|
||||
template <typename Derived>
|
||||
template <return_value_policy policy, typename... Args>
|
||||
object object_api<Derived>::operator()(Args &&...args) const {
|
||||
#if !defined(NDEBUG) && PY_VERSION_HEX >= 0x03060000
|
||||
#ifndef NDEBUG
|
||||
if (!PyGILState_Check()) {
|
||||
pybind11_fail("pybind11::object_api<>::operator() PyGILState_Check() failure.");
|
||||
}
|
||||
|
@ -18,17 +18,6 @@
|
||||
#include <datetime.h>
|
||||
#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(detail)
|
||||
|
||||
|
@ -211,8 +211,8 @@
|
||||
#endif
|
||||
|
||||
#include <Python.h>
|
||||
#if PY_VERSION_HEX < 0x030500f0
|
||||
# error "PYTHON 2 IS NO LONGER SUPPORTED. pybind11 v2.9 was the last to support Python 2."
|
||||
#if PY_VERSION_HEX < 0x03060000
|
||||
# error "PYTHON < 3.6 IS UNSUPPORTED. pybind11 v2.9 was the last to support Python 2 and 3.5."
|
||||
#endif
|
||||
#include <frameobject.h>
|
||||
#include <pythread.h>
|
||||
@ -301,15 +301,6 @@
|
||||
extern "C" PYBIND11_MAYBE_UNUSED 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_STRINGIFY(x) #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
|
||||
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.. */
|
||||
take_ownership,
|
||||
|
||||
@ -454,7 +445,7 @@ enum class return_value_policy : uint8_t {
|
||||
move,
|
||||
|
||||
/** 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
|
||||
the C++ side deletes an object that is still referenced and used by
|
||||
Python. */
|
||||
@ -463,7 +454,7 @@ enum class return_value_policy : uint8_t {
|
||||
/** This policy only applies to methods and properties. It references the
|
||||
object without taking ownership similar to the above
|
||||
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).
|
||||
pybind11 then couples the lifetime of the parent to the child via a
|
||||
reference relationship that ensures that the parent cannot be garbage
|
||||
|
@ -439,10 +439,11 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
|
||||
// instance_registered)
|
||||
|
||||
// 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
|
||||
// they default to using pymalloc, which is designed to be efficient for small allocations
|
||||
// like the one we're doing here; in earlier versions (and for larger allocations) they are
|
||||
// just wrappers around malloc.
|
||||
// in particular, need to be 0). Use Python's memory allocation
|
||||
// functions: Python is using pymalloc, which is designed to be
|
||||
// efficient for small allocations like the one we're doing here;
|
||||
// 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 *));
|
||||
if (!nonsimple.values_and_holders) {
|
||||
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() {
|
||||
#if defined(PYPY_VERSION)
|
||||
return PyThreadState_GET();
|
||||
#elif PY_VERSION_HEX < 0x03050200
|
||||
return (PyThreadState *) _PyThreadState_Current.value;
|
||||
#else
|
||||
return _PyThreadState_UncheckedGet();
|
||||
#endif
|
||||
|
@ -1213,7 +1213,7 @@ public:
|
||||
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
|
||||
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()");
|
||||
}
|
||||
// TODO: Should be reinterpret_steal for Python 3, but Python also steals it again when
|
||||
// returned from PyInit_...
|
||||
// For Python 2, reinterpret_borrow is correct.
|
||||
// returned from PyInit_...
|
||||
// For Python 2, reinterpret_borrow was correct.
|
||||
return reinterpret_borrow<module_>(m);
|
||||
}
|
||||
};
|
||||
|
@ -13,8 +13,7 @@
|
||||
#include <string>
|
||||
|
||||
#ifdef __has_include
|
||||
# if defined(PYBIND11_CPP17) && __has_include(<filesystem>) && \
|
||||
PY_VERSION_HEX >= 0x03060000
|
||||
# if defined(PYBIND11_CPP17) && __has_include(<filesystem>)
|
||||
# include <filesystem>
|
||||
# define PYBIND11_HAS_FILESYSTEM 1
|
||||
# endif
|
||||
|
@ -2,7 +2,7 @@ import nox
|
||||
|
||||
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)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info < (3, 5):
|
||||
msg = "pybind11 does not support Python < 3.5. 2.9 was the last release supporting older Pythons."
|
||||
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)
|
||||
|
||||
|
||||
|
@ -200,7 +200,7 @@ class Pybind11Extension(_Extension): # type: ignore[misc]
|
||||
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={}".format(macos_string)
|
||||
macosx_min = f"-mmacosx-version-min={macos_string}"
|
||||
cflags += [macosx_min]
|
||||
ldflags += [macosx_min]
|
||||
|
||||
@ -322,9 +322,9 @@ def intree_extensions(
|
||||
|
||||
if not exts:
|
||||
msg = (
|
||||
"path {path} is not a child of any of the directories listed "
|
||||
"in 'package_dir' ({package_dir})"
|
||||
).format(path=path, package_dir=package_dir)
|
||||
f"path {path} is not a child of any of the directories listed "
|
||||
f"in 'package_dir' ({package_dir})"
|
||||
)
|
||||
raise ValueError(msg)
|
||||
|
||||
return exts
|
||||
@ -419,7 +419,7 @@ class ParallelCompile:
|
||||
self.default = default
|
||||
self.max = max
|
||||
self.needs_recompile = needs_recompile
|
||||
self._old = [] # type: List[CCompilerMethod]
|
||||
self._old: List[CCompilerMethod] = []
|
||||
|
||||
def function(self) -> CCompilerMethod:
|
||||
"""
|
||||
|
16
setup.cfg
16
setup.cfg
@ -14,7 +14,6 @@ classifiers =
|
||||
Topic :: Utilities
|
||||
Programming Language :: C++
|
||||
Programming Language :: Python :: 3 :: Only
|
||||
Programming Language :: Python :: 3.5
|
||||
Programming Language :: Python :: 3.6
|
||||
Programming Language :: Python :: 3.7
|
||||
Programming Language :: Python :: 3.8
|
||||
@ -38,7 +37,7 @@ project_urls =
|
||||
Chat = https://gitter.im/pybind/Lobby
|
||||
|
||||
[options]
|
||||
python_requires = >=3.5
|
||||
python_requires = >=3.6
|
||||
zip_safe = False
|
||||
|
||||
|
||||
@ -46,14 +45,5 @@ zip_safe = False
|
||||
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
|
||||
|
||||
|
||||
[tool:pytest]
|
||||
timeout = 300
|
||||
extend-ignore = E203, E722, B950
|
||||
select = C,E,F,N,W,B,B9
|
||||
|
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
|
||||
|
||||
@ -41,12 +41,10 @@ def build_expected_version_hex(matches: Dict[str, str]) -> str:
|
||||
serial = int(level_serial[len(level) :])
|
||||
break
|
||||
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)
|
||||
version_hex_str = "{:02x}{:02x}{:02x}{}{:x}".format(
|
||||
major, minor, patch, level[:1], serial
|
||||
)
|
||||
return "0x{}".format(version_hex_str.upper())
|
||||
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
|
||||
@ -66,7 +64,7 @@ to_src = (
|
||||
|
||||
|
||||
# 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")
|
||||
exec(code, loc)
|
||||
version = loc["__version__"]
|
||||
@ -75,17 +73,13 @@ version = loc["__version__"]
|
||||
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 = "PYBIND11_VERSION_HEX {} does not match expected value {}!".format(
|
||||
version_hex, exp_version_hex
|
||||
)
|
||||
msg = f"PYBIND11_VERSION_HEX {version_hex} does not match expected value {exp_version_hex}!"
|
||||
raise RuntimeError(msg)
|
||||
|
||||
|
||||
|
@ -145,9 +145,9 @@ def test_build_sdist(monkeypatch, tmpdir):
|
||||
contents = f.read().decode("utf8")
|
||||
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 |= {"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
|
||||
@ -200,9 +200,9 @@ def test_build_global_dist(monkeypatch, tmpdir):
|
||||
) as f:
|
||||
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 |= {"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:
|
||||
@ -227,7 +227,7 @@ def tests_build_wheel(monkeypatch, tmpdir):
|
||||
|
||||
(wheel,) = tmpdir.visit("*.whl")
|
||||
|
||||
files = {"pybind11/{}".format(n) for n in all_files}
|
||||
files = {f"pybind11/{n}" for n in all_files}
|
||||
files |= {
|
||||
"dist-info/LICENSE",
|
||||
"dist-info/METADATA",
|
||||
@ -241,9 +241,7 @@ def tests_build_wheel(monkeypatch, tmpdir):
|
||||
names = z.namelist()
|
||||
|
||||
trimmed = {n for n in names if "dist-info" not in n}
|
||||
trimmed |= {
|
||||
"dist-info/{}".format(n.split("/", 1)[-1]) for n in names if "dist-info" in n
|
||||
}
|
||||
trimmed |= {f"dist-info/{n.split('/', 1)[-1]}" for n in names if "dist-info" in n}
|
||||
assert files == trimmed
|
||||
|
||||
|
||||
@ -257,8 +255,8 @@ def tests_build_global_wheel(monkeypatch, tmpdir):
|
||||
|
||||
(wheel,) = tmpdir.visit("*.whl")
|
||||
|
||||
files = {"data/data/{}".format(n) for n in src_files}
|
||||
files |= {"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",
|
||||
|
@ -18,7 +18,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
|
||||
(tmpdir / "setup.py").write_text(
|
||||
dedent(
|
||||
"""\
|
||||
f"""\
|
||||
import sys
|
||||
sys.path.append({MAIN_DIR!r})
|
||||
|
||||
@ -51,7 +51,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
|
||||
ext_modules=ext_modules,
|
||||
)
|
||||
"""
|
||||
).format(MAIN_DIR=MAIN_DIR, std=std, parallel=parallel),
|
||||
),
|
||||
encoding="ascii",
|
||||
)
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
[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
|
||||
# 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
|
||||
|
@ -1,12 +1,8 @@
|
||||
numpy==1.16.6; python_version<"3.6" and sys_platform!="win32" and platform_python_implementation!="PyPy"
|
||||
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.21.5; platform_python_implementation=="PyPy" and sys_platform=="linux" and python_version=="3.7"
|
||||
numpy==1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
|
||||
numpy==1.21.3; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.11"
|
||||
py @ git+https://github.com/pytest-dev/py; python_version>="3.11"
|
||||
pytest==4.6.9; python_version<"3.5"
|
||||
pytest==6.1.2; python_version=="3.5"
|
||||
pytest==6.2.4; python_version>="3.6"
|
||||
numpy==1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10"
|
||||
numpy==1.22.2; platform_python_implementation!="PyPy" and python_version>="3.10" and python_version<"3.11"
|
||||
pytest==7.0.0
|
||||
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.6" and python_version<"3.10"
|
||||
scipy==1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10"
|
||||
scipy==1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10"
|
||||
|
@ -50,7 +50,7 @@ def test_single_char_arguments():
|
||||
"""Tests failures for passing invalid inputs to char-accepting functions"""
|
||||
|
||||
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"
|
||||
|
||||
|
@ -17,7 +17,7 @@ def test_callbacks():
|
||||
return "func2", a, b, c, d
|
||||
|
||||
def func3(a):
|
||||
return "func3({})".format(a)
|
||||
return f"func3({a})"
|
||||
|
||||
assert m.test_callback1(func1) == "func1"
|
||||
assert m.test_callback2(func2) == ("func2", "Hello", "x", True, 5)
|
||||
@ -188,14 +188,8 @@ def test_callback_num_times():
|
||||
if not rep:
|
||||
print()
|
||||
print(
|
||||
"callback_num_times: {:d} million / {:.3f} seconds = {:.3f} million / second".format(
|
||||
num_millions, td, rate
|
||||
)
|
||||
f"callback_num_times: {num_millions:d} million / {td:.3f} seconds = {rate:.3f} million / second"
|
||||
)
|
||||
if len(rates) > 1:
|
||||
print("Min Mean Max")
|
||||
print(
|
||||
"{:6.3f} {:6.3f} {:6.3f}".format(
|
||||
min(rates), sum(rates) / len(rates), max(rates)
|
||||
)
|
||||
)
|
||||
print(f"{min(rates):6.3f} {sum(rates) / len(rates):6.3f} {max(rates):6.3f}")
|
||||
|
@ -100,7 +100,7 @@ SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
|
||||
)
|
||||
def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
|
||||
if tz is not None:
|
||||
monkeypatch.setenv("TZ", "/usr/share/zoneinfo/{}".format(tz))
|
||||
monkeypatch.setenv("TZ", f"/usr/share/zoneinfo/{tz}")
|
||||
|
||||
# Roundtrip the time
|
||||
datetime2 = m.test_chrono2(time1)
|
||||
|
@ -5,4 +5,4 @@ import test_cmake_build
|
||||
assert isinstance(__file__, str) # Test this is properly set
|
||||
|
||||
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_1(ref) == ref.diagonal(1))
|
||||
for i in range(-5, 7):
|
||||
assert np.all(
|
||||
m.diagonal_n(ref, i) == ref.diagonal(i)
|
||||
), "m.diagonal_n({})".format(i)
|
||||
assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), f"m.diagonal_n({i})"
|
||||
|
||||
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:])
|
||||
@ -236,7 +234,7 @@ def test_eigen_ref_to_python():
|
||||
mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
|
||||
assert np.all(
|
||||
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):
|
||||
|
@ -88,7 +88,7 @@ def test_python_call_in_catch():
|
||||
def ignore_pytest_unraisable_warning(f):
|
||||
unraisable = "PytestUnraisableExceptionWarning"
|
||||
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)
|
||||
else:
|
||||
return f
|
||||
|
@ -18,9 +18,7 @@ def test_dtypes():
|
||||
assert check.numpy == check.pybind11, check
|
||||
if check.numpy.num != check.pybind11.num:
|
||||
print(
|
||||
"NOTE: typenum mismatch for {}: {} != {}".format(
|
||||
check, check.numpy.num, check.pybind11.num
|
||||
)
|
||||
f"NOTE: typenum mismatch for {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:
|
||||
with pytest.raises(IndexError) as excinfo:
|
||||
func(arr, *([0] * dim))
|
||||
assert str(excinfo.value) == "index dimension mismatch: {} (ndim = 2)".format(
|
||||
dim
|
||||
)
|
||||
assert str(excinfo.value) == f"index dimension mismatch: {dim} (ndim = 2)"
|
||||
|
||||
|
||||
def test_at(arr):
|
||||
@ -192,8 +188,6 @@ def test_make_empty_shaped_array():
|
||||
|
||||
def test_wrap():
|
||||
def assert_references(a, b, base=None):
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
if base is None:
|
||||
base = a
|
||||
assert a is not b
|
||||
@ -204,7 +198,8 @@ def test_wrap():
|
||||
assert a.flags.f_contiguous == b.flags.f_contiguous
|
||||
assert a.flags.writeable == b.flags.writeable
|
||||
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
|
||||
else:
|
||||
assert a.flags.updateifcopy == b.flags.updateifcopy
|
||||
|
@ -14,7 +14,7 @@ def simple_dtype():
|
||||
return np.dtype(
|
||||
{
|
||||
"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)],
|
||||
}
|
||||
)
|
||||
@ -125,7 +125,7 @@ def test_dtype(simple_dtype):
|
||||
assert [x.replace(" ", "") for x in m.print_dtypes()] == [
|
||||
simple_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_nested_fmt(),
|
||||
"[('a','S3'),('b','S3')]",
|
||||
|
@ -12,7 +12,7 @@ def test_string_list():
|
||||
assert lst.back() == "Element 2"
|
||||
|
||||
for i, k in enumerate(lst, start=1):
|
||||
assert k == "Element {}".format(i)
|
||||
assert k == f"Element {i}"
|
||||
lst.pop_back()
|
||||
assert m.print_opaque_list(lst) == "Opaque list: [Element 1]"
|
||||
|
||||
|
@ -305,8 +305,8 @@ def test_non_converting_constructors():
|
||||
for move in [True, False]:
|
||||
with pytest.raises(TypeError) as excinfo:
|
||||
m.nonconverting_constructor(t, v, move)
|
||||
expected_error = "Object of type '{}' is not an instance of '{}'".format(
|
||||
type(v).__name__, t
|
||||
expected_error = (
|
||||
f"Object of type '{type(v).__name__}' is not an instance of '{t}'"
|
||||
)
|
||||
assert str(excinfo.value) == expected_error
|
||||
|
||||
|
@ -1,20 +1,10 @@
|
||||
import pytest
|
||||
from pytest import approx
|
||||
|
||||
from pybind11_tests import ConstructorStats
|
||||
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():
|
||||
assert m.make_forward_slice_size_t() == slice(0, -1, 1)
|
||||
assert m.make_reversed_slice_object() == slice(None, None, -1)
|
||||
@ -117,7 +107,8 @@ def test_sequence():
|
||||
assert 12.34 not in s
|
||||
s[0], s[3] = 12.34, 56.78
|
||||
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)
|
||||
assert cstats.values() == ["of size", "5"]
|
||||
@ -132,14 +123,14 @@ def test_sequence():
|
||||
assert cstats.values() == ["of size", "0"]
|
||||
|
||||
expected = [0, 56.78, 0, 0, 12.34]
|
||||
assert allclose(rev, expected)
|
||||
assert allclose(rev2, expected)
|
||||
assert rev == approx(expected, rel=1e-05)
|
||||
assert rev2 == approx(expected, rel=1e-05)
|
||||
assert rev == rev2
|
||||
|
||||
rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
|
||||
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
|
||||
del it
|
||||
|
@ -15,7 +15,7 @@ def test_smart_ptr(capture):
|
||||
m.print_object_2(o)
|
||||
m.print_object_3(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(
|
||||
[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)
|
||||
|
||||
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)
|
||||
assert cstats.alive() == 0
|
||||
expected_values = ["MyObject1[{}]".format(i) for i in range(1, 7)] + [
|
||||
"MyObject1[7]"
|
||||
] * 4
|
||||
expected_values = [f"MyObject1[{i}]" for i in range(1, 7)] + ["MyObject1[7]"] * 4
|
||||
assert cstats.values() == expected_values
|
||||
assert cstats.default_constructions == 0
|
||||
assert cstats.copy_constructions == 0
|
||||
@ -57,7 +55,7 @@ def test_smart_ptr(capture):
|
||||
m.print_myobject2_2(o)
|
||||
m.print_myobject2_3(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)
|
||||
assert cstats.alive() == 1
|
||||
@ -80,7 +78,7 @@ def test_smart_ptr(capture):
|
||||
m.print_myobject3_2(o)
|
||||
m.print_myobject3_3(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)
|
||||
assert cstats.alive() == 1
|
||||
|
@ -13,7 +13,7 @@ def test_override(capture, msg):
|
||||
self.data = "Hello world"
|
||||
|
||||
def run(self, value):
|
||||
print("ExtendedExampleVirt::run(%i), calling parent.." % value)
|
||||
print(f"ExtendedExampleVirt::run({value}), calling parent..")
|
||||
return super().run(value + 1)
|
||||
|
||||
def run_bool(self):
|
||||
@ -24,7 +24,7 @@ def test_override(capture, msg):
|
||||
return "override1"
|
||||
|
||||
def pure_virtual(self):
|
||||
print("ExtendedExampleVirt::pure_virtual(): %s" % self.data)
|
||||
print(f"ExtendedExampleVirt::pure_virtual(): {self.data}")
|
||||
|
||||
class ExtendedExampleVirt2(ExtendedExampleVirt):
|
||||
def __init__(self, state):
|
||||
|
@ -92,7 +92,7 @@ endif()
|
||||
|
||||
# Use the Python interpreter to find the libs.
|
||||
if(NOT PythonLibsNew_FIND_VERSION)
|
||||
set(PythonLibsNew_FIND_VERSION "3.5")
|
||||
set(PythonLibsNew_FIND_VERSION "3.6")
|
||||
endif()
|
||||
|
||||
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}
|
||||
|
@ -13,7 +13,7 @@ lib = sys.argv[1]
|
||||
save = sys.argv[2]
|
||||
|
||||
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)
|
||||
|
||||
@ -28,7 +28,7 @@ if os.path.exists(save):
|
||||
if change == 0:
|
||||
print(" (no change)")
|
||||
else:
|
||||
print(" (change of {:+} bytes = {:+.2%})".format(change, change / oldsize))
|
||||
print(f" (change of {change:+} bytes = {change / oldsize:+.2%})")
|
||||
else:
|
||||
print()
|
||||
|
||||
|
@ -193,7 +193,7 @@ Using ``find_package`` with version info is not recommended except for release v
|
||||
.. code-block:: cmake
|
||||
|
||||
find_package(pybind11 CONFIG)
|
||||
find_package(pybind11 2.0 EXACT CONFIG REQUIRED)
|
||||
find_package(pybind11 2.9 EXACT CONFIG REQUIRED)
|
||||
|
||||
#]=============================================================================]
|
||||
@PACKAGE_INIT@
|
||||
|
@ -32,7 +32,7 @@ if(NOT Python_FOUND AND NOT Python3_FOUND)
|
||||
set(Python_ROOT_DIR "$ENV{pythonLocation}")
|
||||
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 this behavior is not desired, FindPython _before_ pybind11.
|
||||
|
@ -43,7 +43,7 @@ endif()
|
||||
|
||||
# A user can set versions manually too
|
||||
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 "")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# 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.
|
||||
|
@ -1,5 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Setup script (in the sdist or in tools/setup_main.py in the repository)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user