Python 2 removal part 1: tests (C++ code is intentionally ~untouched) (#3688)

* `#error BYE_BYE_GOLDEN_SNAKE`

* Removing everything related to 2.7 from ci.yml

* Commenting-out Centos7

* Removing `PYTHON: 27` from .appveyor.yml

* "PY2" removal, mainly from tests. C++ code is not touched.

* Systematic removal of `u` prefix from `u"..."` and `u'...'` literals. Collateral cleanup of a couple minor other things.

* Cleaning up around case-insensitive hits for `[^a-z]py.*2` in tests/.

* Removing obsolete Python 2 mention in compiling.rst

* Proper `#error` for Python 2.

* Using PY_VERSION_HEX to guard `#error "PYTHON 2 IS NO LONGER SUPPORTED.`

* chore: bump pre-commit

* style: run pre-commit for pyupgrade 3+

* tests: use sys.version_info, not PY

* chore: more Python 2 removal

* Uncommenting Centos7 block (PR #3691 showed that it is working again).

* Update pre-commit hooks

* Fix pre-commit hook

* refactor: remove Python 2 from CMake

* refactor: remove Python 2 from setup code

* refactor: simplify, better static typing

* feat: fail with nice messages

* refactor: drop Python 2 C++ code

* docs: cleanup for Python 3

* revert: intree

revert: intree

* docs: minor touchup to py2 statement

Co-authored-by: Henry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: Aaron Gokaslan <skylion.aaron@gmail.com>
This commit is contained in:
Ralf W. Grosse-Kunstleve 2022-02-10 18:28:08 -08:00 committed by GitHub
parent 46dcd9bc75
commit 6493f496e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
102 changed files with 529 additions and 1334 deletions

View File

@ -11,8 +11,6 @@ environment:
matrix:
- PYTHON: 36
CONFIG: Debug
- PYTHON: 27
CONFIG: Debug
install:
- ps: |
$env:CMAKE_GENERATOR = "Visual Studio 14 2015"

View File

@ -25,7 +25,6 @@ jobs:
matrix:
runs-on: [ubuntu-latest, windows-2022, macos-latest]
python:
- '2.7'
- '3.5'
- '3.6'
- '3.9'
@ -49,13 +48,9 @@ jobs:
python: '3.6'
args: >
-DPYBIND11_FINDPYTHON=ON
- runs-on: macos-latest
python: 'pypy-2.7'
# Inject a couple Windows 2019 runs
- runs-on: windows-2019
python: '3.9'
- runs-on: windows-2019
python: '2.7'
name: "🐍 ${{ matrix.python }} • ${{ matrix.runs-on }} • x64 ${{ matrix.args }}"
runs-on: ${{ matrix.runs-on }}
@ -168,22 +163,6 @@ jobs:
- name: Interface test
run: cmake --build build2 --target test_cmake_build
# Eventually Microsoft might have an action for setting up
# MSVC, but for now, this action works:
- name: Prepare compiler environment for Windows 🐍 2.7
if: matrix.python == 2.7 && runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1.10.0
with:
arch: x64
# This makes two environment variables available in the following step(s)
- name: Set Windows 🐍 2.7 environment variables
if: matrix.python == 2.7 && runner.os == 'Windows'
shell: bash
run: |
echo "DISTUTILS_USE_SDK=1" >> $GITHUB_ENV
echo "MSSdk=1" >> $GITHUB_ENV
# This makes sure the setup_helpers module can build packages using
# setuptools
- name: Setuptools helpers test
@ -784,7 +763,6 @@ jobs:
fail-fast: false
matrix:
python:
- 2.7
- 3.6
- 3.7
# todo: check/cpptest does not support 3.8+ yet
@ -832,17 +810,12 @@ jobs:
fail-fast: false
matrix:
python:
- 2.7
- 3.5
- 3.7
std:
- 14
include:
- python: 2.7
std: 17
args: >
-DCMAKE_CXX_FLAGS="/permissive- /EHsc /GR"
- python: 3.7
std: 17
args: >

View File

@ -17,19 +17,19 @@ env:
jobs:
# This builds the sdists and wheels and makes sure the files are exactly as
# expected. Using Windows and Python 2.7, since that is often the most
# expected. Using Windows and Python 3.6, since that is often the most
# challenging matrix element.
test-packaging:
name: 🐍 2.7 • 📦 tests • windows-latest
name: 🐍 3.6 • 📦 tests • windows-latest
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- name: Setup 🐍 2.7
- name: Setup 🐍 3.6
uses: actions/setup-python@v2
with:
python-version: 2.7
python-version: 3.6
- name: Prepare env
run: |

View File

@ -29,14 +29,15 @@ repos:
- id: mixed-line-ending
- id: requirements-txt-fixer
- id: trailing-whitespace
- id: fix-encoding-pragma
exclude: ^noxfile.py$
# Upgrade old Python syntax
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py3-plus]
# Nicely sort includes
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
hooks:
@ -44,20 +45,21 @@ repos:
# Black, the code formatter, natively supports pre-commit
- repo: https://github.com/psf/black
rev: 21.12b0 # 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.0
rev: v1.12.1
hooks:
- id: blacken-docs
additional_dependencies:
- black==21.12b0 # keep in sync with black hook
- black==22.1.0 # keep in sync with black hook
# Changes tabs to spaces
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.1.10
rev: v1.1.11
hooks:
- id: remove-tabs
@ -67,12 +69,15 @@ repos:
hooks:
- id: pycln
# Checking for common mistakes
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0
hooks:
- id: python-check-blanket-noqa
- id: python-check-blanket-type-ignore
- id: python-no-log-warn
# Python 3.6
# - id: python-use-type-annotations
- id: rst-backticks
- id: rst-directive-colons
- id: rst-inline-touching-normal
@ -87,6 +92,7 @@ repos:
- pep8-naming
exclude: ^(docs/.*|tools/.*)$
# Automatically remove noqa that are not used
- repo: https://github.com/asottile/yesqa
rev: v1.3.0
hooks:
@ -107,9 +113,9 @@ repos:
rev: v0.931
hooks:
- id: mypy
# Running per-file misbehaves a bit, so just run on all files, it's fast
pass_filenames: false
additional_dependencies: [typed_ast]
args: [--show-error-codes]
exclude: ^(tests|docs)/
additional_dependencies: [nox, rich]
# Checks the manifest for missing files (native support)
- repo: https://github.com/mgedmin/check-manifest
@ -120,6 +126,7 @@ repos:
stages: [manual]
additional_dependencies: [cmake, ninja]
# Check for spelling
- repo: https://github.com/codespell-project/codespell
rev: v2.1.0
hooks:
@ -127,20 +134,22 @@ repos:
exclude: ".supp$"
args: ["-L", "nd,ot,thist"]
# Check for common shell mistakes
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.8.0.3
rev: v0.8.0.4
hooks:
- id: shellcheck
# The original pybind11 checks for a few C++ style items
# Disallow some common capitalization mistakes
- repo: local
hooks:
- id: disallow-caps
name: Disallow improper capitalization
language: pygrep
entry: PyBind|Numpy|Cmake|CCache|PyTest
exclude: .pre-commit-config.yaml
exclude: ^\.pre-commit-config.yaml$
# Clang format the codebase automatically
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v13.0.0"
hooks:

View File

@ -1,6 +1,5 @@
recursive-include pybind11/include/pybind11 *.h
recursive-include pybind11 *.py
recursive-include pybind11 py.typed
recursive-include pybind11 *.pyi
include pybind11/share/cmake/pybind11/*.cmake
include LICENSE README.rst pyproject.toml setup.py setup.cfg

View File

@ -34,7 +34,7 @@ dependency.
Think of this library as a tiny self-contained version of Boost.Python
with everything stripped away that isnt relevant for binding
generation. Without comments, the core header files only require ~4K
lines of code and depend on Python (2.7 or 3.5+, or PyPy) and the C++
lines of code and depend on Python (3.5+, 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 2.7, 3.5+, and PyPy/PyPy3 7.3 are supported with an
implementation-agnostic interface.
- 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).
- It is possible to bind C++11 lambda functions with captured
variables. The lambda capture data is stored inside the resulting

View File

@ -18,5 +18,4 @@ ALIASES += "endrst=\endverbatim"
QUIET = YES
WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO
PREDEFINED = PY_MAJOR_VERSION=3 \
PYBIND11_NOINLINE
PREDEFINED = PYBIND11_NOINLINE

View File

@ -1,14 +1,6 @@
Strings, bytes and Unicode conversions
######################################
.. note::
This section discusses string handling in terms of Python 3 strings. For
Python 2.7, replace all occurrences of ``str`` with ``unicode`` and
``bytes`` with ``str``. Python 2.7 users may find it best to use ``from
__future__ import unicode_literals`` to avoid unintentionally using ``str``
instead of ``unicode``.
Passing Python strings to C++
=============================
@ -58,9 +50,9 @@ Passing bytes to C++
--------------------
A Python ``bytes`` object will be passed to C++ functions that accept
``std::string`` or ``char*`` *without* conversion. On Python 3, in order to
make a function *only* accept ``bytes`` (and not ``str``), declare it as taking
a ``py::bytes`` argument.
``std::string`` or ``char*`` *without* conversion. In order to make a function
*only* accept ``bytes`` (and not ``str``), declare it as taking a ``py::bytes``
argument.
Returning C++ strings to Python
@ -204,11 +196,6 @@ decoded to Python ``str``.
}
);
.. warning::
Wide character strings may not work as described on Python 2.7 or Python
3.3 compiled with ``--enable-unicode=ucs2``.
Strings in multibyte encodings such as Shift-JIS must transcoded to a
UTF-8/16/32 before being returned to Python.

View File

@ -133,14 +133,14 @@ a virtual method call.
>>> from example import *
>>> d = Dog()
>>> call_go(d)
u'woof! woof! woof! '
'woof! woof! woof! '
>>> class Cat(Animal):
... def go(self, n_times):
... return "meow! " * n_times
...
>>> c = Cat()
>>> call_go(c)
u'meow! meow! meow! '
'meow! meow! meow! '
If you are defining a custom constructor in a derived Python class, you *must*
ensure that you explicitly call the bound C++ constructor using ``__init__``,
@ -813,26 +813,21 @@ An instance can now be pickled as follows:
.. code-block:: python
try:
import cPickle as pickle # Use cPickle on Python 2.7
except ImportError:
import pickle
p = Pickleable("test_value")
p.setExtra(15)
data = pickle.dumps(p, 2)
data = pickle.dumps(p)
.. note::
Note that only the cPickle module is supported on Python 2.7.
The second argument to ``dumps`` is also crucial: it selects the pickle
protocol version 2, since the older version 1 is not supported. Newer
versions are also fine—for instance, specify ``-1`` to always use the
latest available version. Beware: failure to follow these instructions
will cause important pybind11 memory allocation routines to be skipped
during unpickling, which will likely lead to memory corruption and/or
segmentation faults.
If given, the second argument to ``dumps`` must be 2 or larger - 0 and 1 are
not supported. Newer versions are also fine; for instance, specify ``-1`` to
always use the latest available version. Beware: failure to follow these
instructions will cause important pybind11 memory allocation routines to be
skipped during unpickling, which will likely lead to memory corruption
and/or segmentation faults. Python defaults to version 3 (Python 3-3.7) and
version 4 for Python 3.8+.
.. seealso::
@ -849,11 +844,9 @@ Python normally uses references in assignments. Sometimes a real copy is needed
to prevent changing all copies. The ``copy`` module [#f5]_ provides these
capabilities.
On Python 3, a class with pickle support is automatically also (deep)copy
A class with pickle support is automatically also (deep)copy
compatible. However, performance can be improved by adding custom
``__copy__`` and ``__deepcopy__`` methods. With Python 2.7, these custom methods
are mandatory for (deep)copy compatibility, because pybind11 only supports
cPickle.
``__copy__`` and ``__deepcopy__`` methods.
For simple classes (deep)copy can be enabled by using the copy constructor,
which should look as follows:

View File

@ -328,8 +328,8 @@ an invalid state.
Chaining exceptions ('raise from')
==================================
In Python 3.3 a mechanism for indicating that exceptions were caused by other
exceptions was introduced:
Python has a mechanism for indicating that exceptions were caused by other
exceptions:
.. code-block:: py
@ -340,7 +340,7 @@ exceptions was introduced:
To do a similar thing in pybind11, you can use the ``py::raise_from`` function. It
sets the current python error indicator, so to continue propagating the exception
you should ``throw py::error_already_set()`` (Python 3 only).
you should ``throw py::error_already_set()``.
.. code-block:: cpp

View File

@ -398,8 +398,6 @@ Ellipsis
Python 3 provides a convenient ``...`` ellipsis notation that is often used to
slice multidimensional arrays. For instance, the following snippet extracts the
middle dimensions of a tensor with the first and last index set to zero.
In Python 2, the syntactic sugar ``...`` is not available, but the singleton
``Ellipsis`` (of type ``ellipsis``) can still be used directly.
.. code-block:: python
@ -414,8 +412,6 @@ operation on the C++ side:
py::array a = /* A NumPy array */;
py::array b = a[py::make_tuple(0, py::ellipsis(), 0)];
.. versionchanged:: 2.6
``py::ellipsis()`` is now also available in Python 2.
Memory view
===========
@ -455,9 +451,5 @@ We can also use ``memoryview::from_memory`` for a simple 1D contiguous buffer:
);
})
.. note::
``memoryview::from_memory`` is not available in Python 2.
.. versionchanged:: 2.6
``memoryview::from_memory`` added.

View File

@ -166,12 +166,12 @@ load and execute the example:
.. code-block:: pycon
$ python
Python 2.7.10 (default, Aug 22 2015, 20:33:39)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)] on darwin
Python 3.9.10 (main, Jan 15 2022, 11:48:04)
[Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
>>> example.add(1, 2)
3L
3
>>>
.. _keyword_args:

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime as dt
import os
import random
@ -75,7 +74,7 @@ def generate_dummy_code_boost(nclasses=10):
for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]:
print("{")
for i in range(0, 10):
nclasses = 2 ** i
nclasses = 2**i
with open("test.cpp", "w") as f:
f.write(codegen(nclasses))
n1 = dt.datetime.now()

View File

@ -48,10 +48,10 @@ interactive Python session demonstrating this example is shown below:
>>> print(p)
<example.Pet object at 0x10cd98060>
>>> p.getName()
u'Molly'
'Molly'
>>> p.setName("Charly")
>>> p.getName()
u'Charly'
'Charly'
.. seealso::
@ -124,10 +124,10 @@ This makes it possible to write
>>> p = example.Pet("Molly")
>>> p.name
u'Molly'
'Molly'
>>> p.name = "Charly"
>>> p.name
u'Charly'
'Charly'
Now suppose that ``Pet::name`` was a private internal variable
that can only be accessed via setters and getters.
@ -282,9 +282,9 @@ expose fields and methods of both types:
>>> p = example.Dog("Molly")
>>> p.name
u'Molly'
'Molly'
>>> p.bark()
u'woof!'
'woof!'
The C++ classes defined above are regular non-polymorphic types with an
inheritance relationship. This is reflected in Python:
@ -332,7 +332,7 @@ will automatically recognize this:
>>> type(p)
PolymorphicDog # automatically downcast
>>> p.bark()
u'woof!'
'woof!'
Given a pointer to a polymorphic base, pybind11 performs automatic downcasting
to the actual derived type. Note that this goes beyond the usual situation in

View File

@ -462,11 +462,8 @@ available in all modes. The targets provided are:
``pybind11::headers``
Just the pybind11 headers and minimum compile requirements
``pybind11::python2_no_register``
Quiets the warning/error when mixing C++14 or higher and Python 2
``pybind11::pybind11``
Python headers + ``pybind11::headers`` + ``pybind11::python2_no_register`` (Python 2 only)
Python headers + ``pybind11::headers``
``pybind11::python_link_helper``
Just the "linking" part of pybind11:module
@ -577,21 +574,12 @@ On Linux, you can compile an example such as the one given in
$ c++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)
The flags given here assume that you're using Python 3. For Python 2, just
change the executable appropriately (to ``python`` or ``python2``).
The ``python3 -m pybind11 --includes`` command fetches the include paths for
both pybind11 and Python headers. This assumes that pybind11 has been installed
using ``pip`` or ``conda``. If it hasn't, you can also manually specify
``-I <path-to-pybind11>/include`` together with the Python includes path
``python3-config --includes``.
Note that Python 2.7 modules don't use a special suffix, so you should simply
use ``example.so`` instead of ``example$(python3-config --extension-suffix)``.
Besides, the ``--extension-suffix`` option may or may not be available, depending
on the distribution; in the latter case, the module extension can be manually
set to ``.so``.
On macOS: the build command is almost the same but it also requires passing
the ``-undefined dynamic_lookup`` flag so as to ignore missing symbols when
building the module:

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# pybind11 documentation build configuration file, created by
# sphinx-quickstart on Sun Oct 11 19:23:48 2015.

View File

@ -8,9 +8,7 @@ Frequently asked questions
filename of the extension library (without suffixes such as ``.so``).
2. If the above did not fix the issue, you are likely using an incompatible
version of Python (for instance, the extension library was compiled against
Python 2, while the interpreter is running on top of some version of Python
3, or vice versa).
version of Python that does not match what you compiled with.
"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``"
========================================================================
@ -289,27 +287,7 @@ Conflicts can arise, however, when using pybind11 in a project that *also* uses
the CMake Python detection in a system with several Python versions installed.
This difference may cause inconsistencies and errors if *both* mechanisms are
used in the same project. Consider the following CMake code executed in a
system with Python 2.7 and 3.x installed:
.. code-block:: cmake
find_package(PythonInterp)
find_package(PythonLibs)
find_package(pybind11)
It will detect Python 2.7 and pybind11 will pick it as well.
In contrast this code:
.. code-block:: cmake
find_package(pybind11)
find_package(PythonInterp)
find_package(PythonLibs)
will detect Python 3.x for pybind11 and may crash on
``find_package(PythonLibs)`` afterwards.
used in the same project.
There are three possible solutions:

View File

@ -325,7 +325,7 @@ public:
res = 0; // None is implicitly converted to False
}
#if defined(PYPY_VERSION)
// On PyPy, check that "__bool__" (or "__nonzero__" on Python 2.7) attr exists
// On PyPy, check that "__bool__" attr exists
else if (hasattr(src, PYBIND11_BOOL_ATTR)) {
res = PyObject_IsTrue(src.ptr());
}
@ -375,37 +375,16 @@ struct string_caster {
static constexpr size_t UTF_N = 8 * sizeof(CharT);
bool load(handle src, bool) {
#if PY_MAJOR_VERSION < 3
object temp;
#endif
handle load_src = src;
if (!src) {
return false;
}
if (!PyUnicode_Check(load_src.ptr())) {
#if PY_MAJOR_VERSION >= 3
return load_bytes(load_src);
#else
if (std::is_same<CharT, char>::value) {
return load_bytes(load_src);
}
// The below is a guaranteed failure in Python 3 when PyUnicode_Check returns false
if (!PYBIND11_BYTES_CHECK(load_src.ptr()))
return false;
temp = reinterpret_steal<object>(PyUnicode_FromObject(load_src.ptr()));
if (!temp) {
PyErr_Clear();
return false;
}
load_src = temp;
#endif
}
#if PY_VERSION_HEX >= 0x03030000
// On Python >= 3.3, for UTF-8 we avoid the need for a temporary `bytes`
// object by using `PyUnicode_AsUTF8AndSize`.
// For UTF-8 we avoid the need for a temporary `bytes` object by using
// `PyUnicode_AsUTF8AndSize`.
if (PYBIND11_SILENCE_MSVC_C4127(UTF_N == 8)) {
Py_ssize_t size = -1;
const auto *buffer
@ -417,7 +396,6 @@ struct string_caster {
value = StringType(buffer, static_cast<size_t>(size));
return true;
}
#endif
auto utfNbytes
= reinterpret_steal<object>(PyUnicode_AsEncodedString(load_src.ptr(),
@ -486,7 +464,7 @@ private:
template <typename C = CharT>
bool load_bytes(enable_if_t<std::is_same<C, char>::value, handle> src) {
if (PYBIND11_BYTES_CHECK(src.ptr())) {
// We were passed a Python 3 raw bytes; accept it into a std::string or char*
// We were passed raw bytes; accept it into a std::string or char*
// without any encoding attempt.
const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr());
if (bytes) {
@ -922,18 +900,6 @@ struct pyobject_caster {
template <typename T = type, enable_if_t<std::is_base_of<object, T>::value, int> = 0>
bool load(handle src, bool /* convert */) {
#if PY_MAJOR_VERSION < 3 && !defined(PYBIND11_STR_LEGACY_PERMISSIVE)
// For Python 2, without this implicit conversion, Python code would
// need to be cluttered with six.ensure_text() or similar, only to be
// un-cluttered later after Python 2 support is dropped.
if (PYBIND11_SILENCE_MSVC_C4127(std::is_same<T, str>::value) && isinstance<bytes>(src)) {
PyObject *str_from_bytes = PyUnicode_FromEncodedObject(src.ptr(), "utf-8", nullptr);
if (!str_from_bytes)
throw error_already_set();
value = reinterpret_steal<type>(str_from_bytes);
return true;
}
#endif
if (!isinstance<type>(src)) {
return false;
}
@ -1313,7 +1279,7 @@ public:
/// \ingroup annotations
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of
/// an unnamed '*' argument (in Python 3)
/// an unnamed '*' argument
struct kw_only {};
/// \ingroup annotations

View File

@ -15,12 +15,12 @@
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail)
#if PY_VERSION_HEX >= 0x03030000 && !defined(PYPY_VERSION)
#if !defined(PYPY_VERSION)
# define PYBIND11_BUILTIN_QUALNAME
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
#else
// In pre-3.3 Python, we still set __qualname__ so that we can produce reliable function type
// signatures; in 3.3+ this macro expands to nothing:
// In PyPy, we still set __qualname__ so that we can produce reliable function type
// signatures; in CPython this macro expands to nothing:
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) \
setattr((PyObject *) obj, "__qualname__", nameobj)
#endif
@ -155,7 +155,6 @@ extern "C" inline int pybind11_meta_setattro(PyObject *obj, PyObject *name, PyOb
}
}
#if PY_MAJOR_VERSION >= 3
/**
* Python 3's PyInstanceMethod_Type hides itself via its tp_descr_get, which prevents aliasing
* methods via cls.attr("m2") = cls.attr("m1"): instead the tp_descr_get returns a plain function,
@ -170,7 +169,6 @@ extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name
}
return PyType_Type.tp_getattro(obj, name);
}
#endif
/// metaclass `__call__` function that is used to create all pybind11 objects.
extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, PyObject *kwargs) {
@ -266,9 +264,7 @@ inline PyTypeObject *make_default_metaclass() {
type->tp_call = pybind11_meta_call;
type->tp_setattro = pybind11_meta_setattro;
#if PY_MAJOR_VERSION >= 3
type->tp_getattro = pybind11_meta_getattro;
#endif
type->tp_dealloc = pybind11_meta_dealloc;
@ -613,9 +609,6 @@ extern "C" inline void pybind11_releasebuffer(PyObject *, Py_buffer *view) {
/// Give this type a buffer interface.
inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) {
heap_type->ht_type.tp_as_buffer = &heap_type->as_buffer;
#if PY_MAJOR_VERSION < 3
heap_type->ht_type.tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
#endif
heap_type->as_buffer.bf_getbuffer = pybind11_getbuffer;
heap_type->as_buffer.bf_releasebuffer = pybind11_releasebuffer;
@ -628,12 +621,8 @@ inline PyObject *make_new_python_type(const type_record &rec) {
auto qualname = name;
if (rec.scope && !PyModule_Check(rec.scope.ptr()) && hasattr(rec.scope, "__qualname__")) {
#if PY_MAJOR_VERSION >= 3
qualname = reinterpret_steal<object>(
PyUnicode_FromFormat("%U.%U", rec.scope.attr("__qualname__").ptr(), name.ptr()));
#else
qualname = str(rec.scope.attr("__qualname__").cast<std::string>() + "." + rec.name);
#endif
}
object module_;
@ -697,15 +686,10 @@ inline PyObject *make_new_python_type(const type_record &rec) {
type->tp_as_number = &heap_type->as_number;
type->tp_as_sequence = &heap_type->as_sequence;
type->tp_as_mapping = &heap_type->as_mapping;
#if PY_VERSION_HEX >= 0x03050000
type->tp_as_async = &heap_type->as_async;
#endif
/* Flags */
type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
#if PY_MAJOR_VERSION < 3
type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
#endif
if (!rec.is_final) {
type->tp_flags |= Py_TPFLAGS_BASETYPE;
}

View File

@ -211,6 +211,9 @@
#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."
#endif
#include <frameobject.h>
#include <pythread.h>
@ -266,70 +269,38 @@
// If UNDEFINED, pybind11::str can only hold PyUnicodeObject, and
// pybind11::isinstance<str>() is true only for pybind11::str.
// However, for Python 2 only (!), the pybind11::str caster
// implicitly decodes bytes to PyUnicodeObject. This is to ease
// implicitly decoded bytes to PyUnicodeObject. This was to ease
// the transition from the legacy behavior to the non-permissive
// behavior.
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions
# define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
# define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check
# define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION
# define PYBIND11_BYTES_CHECK PyBytes_Check
# define PYBIND11_BYTES_FROM_STRING PyBytes_FromString
# define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize
# define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize
# define PYBIND11_BYTES_AS_STRING PyBytes_AsString
# define PYBIND11_BYTES_SIZE PyBytes_Size
# define PYBIND11_LONG_CHECK(o) PyLong_Check(o)
# define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o)
# define PYBIND11_LONG_FROM_SIGNED(o) PyLong_FromSsize_t((ssize_t) (o))
# define PYBIND11_LONG_FROM_UNSIGNED(o) PyLong_FromSize_t((size_t) (o))
# define PYBIND11_BYTES_NAME "bytes"
# define PYBIND11_STRING_NAME "str"
# define PYBIND11_SLICE_OBJECT PyObject
# define PYBIND11_FROM_STRING PyUnicode_FromString
# define PYBIND11_STR_TYPE ::pybind11::str
# define PYBIND11_BOOL_ATTR "__bool__"
# define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_bool)
# define PYBIND11_BUILTINS_MODULE "builtins"
/// Compatibility macros for Python 2 / Python 3 versions TODO: remove
#define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
#define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check
#define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION
#define PYBIND11_BYTES_CHECK PyBytes_Check
#define PYBIND11_BYTES_FROM_STRING PyBytes_FromString
#define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize
#define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize
#define PYBIND11_BYTES_AS_STRING PyBytes_AsString
#define PYBIND11_BYTES_SIZE PyBytes_Size
#define PYBIND11_LONG_CHECK(o) PyLong_Check(o)
#define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(o)
#define PYBIND11_LONG_FROM_SIGNED(o) PyLong_FromSsize_t((ssize_t) (o))
#define PYBIND11_LONG_FROM_UNSIGNED(o) PyLong_FromSize_t((size_t) (o))
#define PYBIND11_BYTES_NAME "bytes"
#define PYBIND11_STRING_NAME "str"
#define PYBIND11_SLICE_OBJECT PyObject
#define PYBIND11_FROM_STRING PyUnicode_FromString
#define PYBIND11_STR_TYPE ::pybind11::str
#define PYBIND11_BOOL_ATTR "__bool__"
#define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_bool)
#define PYBIND11_BUILTINS_MODULE "builtins"
// Providing a separate declaration to make Clang's -Wmissing-prototypes happy.
// See comment for PYBIND11_MODULE below for why this is marked "maybe unused".
# define PYBIND11_PLUGIN_IMPL(name) \
#define PYBIND11_PLUGIN_IMPL(name) \
extern "C" PYBIND11_MAYBE_UNUSED PYBIND11_EXPORT PyObject *PyInit_##name(); \
extern "C" PYBIND11_EXPORT PyObject *PyInit_##name()
#else
# define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyMethod_New(ptr, nullptr, class_)
# define PYBIND11_INSTANCE_METHOD_CHECK PyMethod_Check
# define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyMethod_GET_FUNCTION
# define PYBIND11_BYTES_CHECK PyString_Check
# define PYBIND11_BYTES_FROM_STRING PyString_FromString
# define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize
# define PYBIND11_BYTES_AS_STRING_AND_SIZE PyString_AsStringAndSize
# define PYBIND11_BYTES_AS_STRING PyString_AsString
# define PYBIND11_BYTES_SIZE PyString_Size
# define PYBIND11_LONG_CHECK(o) (PyInt_Check(o) || PyLong_Check(o))
# define PYBIND11_LONG_AS_LONGLONG(o) \
(PyInt_Check(o) ? (long long) PyLong_AsLong(o) : PyLong_AsLongLong(o))
# define PYBIND11_LONG_FROM_SIGNED(o) PyInt_FromSsize_t((ssize_t) o) // Returns long if needed.
# define PYBIND11_LONG_FROM_UNSIGNED(o) PyInt_FromSize_t((size_t) o) // Returns long if needed.
# define PYBIND11_BYTES_NAME "str"
# define PYBIND11_STRING_NAME "unicode"
# define PYBIND11_SLICE_OBJECT PySliceObject
# define PYBIND11_FROM_STRING PyString_FromString
# define PYBIND11_STR_TYPE ::pybind11::bytes
# define PYBIND11_BOOL_ATTR "__nonzero__"
# define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_nonzero)
# define PYBIND11_BUILTINS_MODULE "__builtin__"
// Providing a separate PyInit decl to make Clang's -Wmissing-prototypes happy.
// See comment for PYBIND11_MODULE below for why this is marked "maybe unused".
# define PYBIND11_PLUGIN_IMPL(name) \
static PyObject *pybind11_init_wrapper(); \
extern "C" PYBIND11_MAYBE_UNUSED PYBIND11_EXPORT void init##name(); \
extern "C" PYBIND11_EXPORT void init##name() { (void) pybind11_init_wrapper(); } \
PyObject *pybind11_init_wrapper()
#endif
#if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200
extern "C" {
struct _Py_atomic_address {
@ -362,9 +333,7 @@ PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current;
} \
}
#if PY_VERSION_HEX >= 0x03030000
# define PYBIND11_CATCH_INIT_EXCEPTIONS \
#define PYBIND11_CATCH_INIT_EXCEPTIONS \
catch (pybind11::error_already_set & e) { \
pybind11::raise_from(e, PyExc_ImportError, "initialization failed"); \
return nullptr; \
@ -374,20 +343,6 @@ PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current;
return nullptr; \
}
#else
# define PYBIND11_CATCH_INIT_EXCEPTIONS \
catch (pybind11::error_already_set & e) { \
PyErr_SetString(PyExc_ImportError, e.what()); \
return nullptr; \
} \
catch (const std::exception &e) { \
PyErr_SetString(PyExc_ImportError, e.what()); \
return nullptr; \
}
#endif
/** \rst
***Deprecated in favor of PYBIND11_MODULE***

View File

@ -82,7 +82,7 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
# define PYBIND11_TLS_KEY_INIT(var) PYBIND11_TLS_KEY_REF var = 0;
# define PYBIND11_TLS_KEY_CREATE(var) (((var) = PyThread_create_key()) != -1)
# define PYBIND11_TLS_GET_VALUE(key) PyThread_get_key_value((key))
# if PY_MAJOR_VERSION < 3 || defined(PYPY_VERSION)
# if defined(PYPY_VERSION)
// On CPython < 3.4 and on PyPy, `PyThread_set_key_value` strangely does not set
// the value if it has already been set. Instead, it must first be deleted and
// then set again.
@ -294,7 +294,6 @@ inline internals **&get_internals_pp() {
return internals_pp;
}
#if PY_VERSION_HEX >= 0x03030000
// forward decl
inline void translate_exception(std::exception_ptr);
@ -318,21 +317,11 @@ bool handle_nested_exception(const T &exc, const std::exception_ptr &p) {
return false;
}
#else
template <class T>
bool handle_nested_exception(const T &, std::exception_ptr &) {
return false;
}
#endif
inline bool raise_err(PyObject *exc_type, const char *msg) {
#if PY_VERSION_HEX >= 0x03030000
if (PyErr_Occurred()) {
raise_from(exc_type, msg);
return true;
}
#endif
PyErr_SetString(exc_type, msg);
return false;
}

View File

@ -443,17 +443,10 @@ PYBIND11_NOINLINE void instance::allocate_layout() {
// 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.
#if PY_VERSION_HEX >= 0x03050000
nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
if (!nonsimple.values_and_holders) {
throw std::bad_alloc();
}
#else
nonsimple.values_and_holders = (void **) PyMem_New(void *, space);
if (!nonsimple.values_and_holders)
throw std::bad_alloc();
std::memset(nonsimple.values_and_holders, 0, space * sizeof(void *));
#endif
nonsimple.status
= reinterpret_cast<std::uint8_t *>(&nonsimple.values_and_holders[flags_at]);
}
@ -494,11 +487,9 @@ PYBIND11_NOINLINE std::string error_string() {
PyErr_NormalizeException(&scope.type, &scope.value, &scope.trace);
#if PY_MAJOR_VERSION >= 3
if (scope.trace != nullptr) {
PyException_SetTraceback(scope.value, scope.trace);
}
#endif
#if !defined(PYPY_VERSION)
if (scope.trace) {
@ -547,10 +538,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 < 0x03000000
return _PyThreadState_Current;
#elif PY_VERSION_HEX < 0x03050000
return (PyThreadState *) _Py_atomic_load_relaxed(&_PyThreadState_Current);
#elif PY_VERSION_HEX < 0x03050200
return (PyThreadState *) _PyThreadState_Current.value;
#else

View File

@ -19,15 +19,9 @@
# error Embedding the interpreter is not supported with PyPy
#endif
#if PY_MAJOR_VERSION >= 3
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
#define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
extern "C" PyObject *pybind11_init_impl_##name(); \
extern "C" PyObject *pybind11_init_impl_##name() { return pybind11_init_wrapper_##name(); }
#else
# define PYBIND11_EMBEDDED_MODULE_IMPL(name) \
extern "C" void pybind11_init_impl_##name(); \
extern "C" void pybind11_init_impl_##name() { pybind11_init_wrapper_##name(); }
#endif
/** \rst
Add a new module to the table of builtins for the interpreter. Must be
@ -67,11 +61,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
/// Python 2.7/3.x compatible version of `PyImport_AppendInittab` and error checks.
struct embedded_module {
#if PY_MAJOR_VERSION >= 3
using init_t = PyObject *(*) ();
#else
using init_t = void (*)();
#endif
embedded_module(const char *name, init_t init) {
if (Py_IsInitialized() != 0) {
pybind11_fail("Can't add new modules after the interpreter has been initialized");
@ -86,42 +76,13 @@ struct embedded_module {
struct wide_char_arg_deleter {
void operator()(wchar_t *ptr) const {
#if PY_VERSION_HEX >= 0x030500f0
// API docs: https://docs.python.org/3/c-api/sys.html#c.Py_DecodeLocale
PyMem_RawFree(ptr);
#else
delete[] ptr;
#endif
}
};
inline wchar_t *widen_chars(const char *safe_arg) {
#if PY_VERSION_HEX >= 0x030500f0
wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
#else
wchar_t *widened_arg = nullptr;
// warning C4996: 'mbstowcs': This function or variable may be unsafe.
# if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4996)
# endif
# if defined(HAVE_BROKEN_MBSTOWCS) && HAVE_BROKEN_MBSTOWCS
size_t count = std::strlen(safe_arg);
# else
size_t count = std::mbstowcs(nullptr, safe_arg, 0);
# endif
if (count != static_cast<size_t>(-1)) {
widened_arg = new wchar_t[count + 1];
std::mbstowcs(widened_arg, safe_arg, count + 1);
}
# if defined(_MSC_VER)
# pragma warning(pop)
# endif
#endif
return widened_arg;
}
@ -138,7 +99,6 @@ inline void set_interpreter_argv(int argc, const char *const *argv, bool add_pro
}
auto argv_size = static_cast<size_t>(argc);
#if PY_MAJOR_VERSION >= 3
// SetArgv* on python 3 takes wchar_t, so we have to convert.
std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
std::vector<std::unique_ptr<wchar_t[], wide_char_arg_deleter>> widened_argv_entries;
@ -154,15 +114,6 @@ inline void set_interpreter_argv(int argc, const char *const *argv, bool add_pro
}
auto *pysys_argv = widened_argv.get();
#else
// python 2.x
std::vector<std::string> strings{safe_argv, safe_argv + argv_size};
std::vector<char *> char_strings{argv_size};
for (std::size_t i = 0; i < argv_size; ++i)
char_strings[i] = &strings[i][0];
char **pysys_argv = char_strings.data();
#endif
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
}

View File

@ -20,10 +20,10 @@ PYBIND11_NAMESPACE_BEGIN(detail)
inline void ensure_builtins_in_globals(object &global) {
#if defined(PYPY_VERSION) || PY_VERSION_HEX < 0x03080000
// Running exec and eval on Python 2 and 3 adds `builtins` module under
// `__builtins__` key to globals if not yet present.
// Python 3.8 made PyRun_String behave similarly. Let's also do that for
// older versions, for consistency. This was missing from PyPy3.8 7.3.7.
// Running exec and eval adds `builtins` module under `__builtins__` key to
// globals if not yet present. Python 3.8 made PyRun_String behave
// similarly. Let's also do that for older versions, for consistency. This
// was missing from PyPy3.8 7.3.7.
if (!global.contains("__builtins__"))
global["__builtins__"] = module_::import(PYBIND11_BUILTINS_MODULE);
#else
@ -94,7 +94,7 @@ void exec(const char (&s)[N], object global = globals(), object local = object()
eval<eval_statements>(s, global, local);
}
#if defined(PYPY_VERSION) && PY_VERSION_HEX >= 0x03000000
#if defined(PYPY_VERSION)
template <eval_mode mode = eval_statements>
object eval_file(str, object, object) {
pybind11_fail("eval_file not supported in PyPy3. Use eval");
@ -133,40 +133,18 @@ object eval_file(str fname, object global = globals(), object local = object())
int closeFile = 1;
std::string fname_str = (std::string) fname;
# if PY_VERSION_HEX >= 0x03040000
FILE *f = _Py_fopen_obj(fname.ptr(), "r");
# elif PY_VERSION_HEX >= 0x03000000
FILE *f = _Py_fopen(fname.ptr(), "r");
# else
/* No unicode support in open() :( */
auto fobj = reinterpret_steal<object>(
PyFile_FromString(const_cast<char *>(fname_str.c_str()), const_cast<char *>("r")));
FILE *f = nullptr;
if (fobj)
f = PyFile_AsFile(fobj.ptr());
closeFile = 0;
# endif
if (!f) {
PyErr_Clear();
pybind11_fail("File \"" + fname_str + "\" could not be opened!");
}
// In Python2, this should be encoded by getfilesystemencoding.
// We don't boher setting it since Python2 is past EOL anyway.
// See PR#3233
# if PY_VERSION_HEX >= 0x03000000
if (!global.contains("__file__")) {
global["__file__"] = std::move(fname);
}
# endif
# if PY_VERSION_HEX < 0x03000000 && defined(PYPY_VERSION)
PyObject *result = PyRun_File(f, fname_str.c_str(), start, global.ptr(), local.ptr());
(void) closeFile;
# else
PyObject *result
= PyRun_FileEx(f, fname_str.c_str(), start, global.ptr(), local.ptr(), closeFile);
# endif
if (!result) {
throw error_already_set();

View File

@ -263,11 +263,7 @@ private:
static npy_api lookup() {
module_ m = module_::import("numpy.core.multiarray");
auto c = m.attr("_ARRAY_API");
#if PY_MAJOR_VERSION >= 3
void **api_ptr = (void **) PyCapsule_GetPointer(c.ptr(), NULL);
#else
void **api_ptr = (void **) PyCObject_AsVoidPtr(c.ptr());
#endif
npy_api api;
#define DECL_NPY_API(Func) api.Func##_ = (decltype(api.Func##_)) api_ptr[API_##Func];
DECL_NPY_API(PyArray_GetNDArrayCFeatureVersion);

View File

@ -91,16 +91,6 @@ struct op_ {
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
using op = op_impl<id, ot, Base, L_type, R_type>;
cl.def(op::name(), &op::execute, is_operator(), extra...);
#if PY_MAJOR_VERSION < 3
if (PYBIND11_SILENCE_MSVC_C4127(id == op_truediv)
|| PYBIND11_SILENCE_MSVC_C4127(id == op_itruediv))
cl.def(id == op_itruediv ? "__idiv__"
: ot == op_l ? "__div__"
: "__rdiv__",
&op::execute,
is_operator(),
extra...);
#endif
}
template <typename Class, typename... Extra>
void execute_cast(Class &cl, const Extra &...extra) const {
@ -109,15 +99,6 @@ struct op_ {
using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>;
using op = op_impl<id, ot, Base, L_type, R_type>;
cl.def(op::name(), &op::execute_cast, is_operator(), extra...);
#if PY_MAJOR_VERSION < 3
if (id == op_truediv || id == op_itruediv)
cl.def(id == op_itruediv ? "__idiv__"
: ot == op_l ? "__div__"
: "__rdiv__",
&op::execute,
is_operator(),
extra...);
#endif
}
};

View File

@ -431,9 +431,8 @@ protected:
}
if (auto *tinfo = detail::get_type_info(*t)) {
handle th((PyObject *) tinfo->type);
signature += th.attr("__module__").cast<std::string>() + "." +
// Python 3.3+, but we backport it to earlier versions
th.attr("__qualname__").cast<std::string>();
signature += th.attr("__module__").cast<std::string>() + "."
+ th.attr("__qualname__").cast<std::string>();
} else if (rec->is_new_style_constructor && arg_index == 0) {
// A new-style `__init__` takes `self` as `value_and_holder`.
// Rewrite it to the proper class type.
@ -453,15 +452,6 @@ protected:
pybind11_fail("Internal error while parsing type signature (2)");
}
#if PY_MAJOR_VERSION < 3
if (std::strcmp(rec->name, "__next__") == 0) {
std::free(rec->name);
rec->name = guarded_strdup("next");
} else if (std::strcmp(rec->name, "__bool__") == 0) {
std::free(rec->name);
rec->name = guarded_strdup("__nonzero__");
}
#endif
rec->signature = guarded_strdup(signature.c_str());
rec->args.shrink_to_fit();
rec->nargs = (std::uint16_t) args;
@ -1107,14 +1097,12 @@ protected:
}
append_note_if_missing_header_is_suspected(msg);
#if PY_VERSION_HEX >= 0x03030000
// Attach additional error info to the exception if supported
if (PyErr_Occurred()) {
// #HelpAppreciated: unit test coverage for this branch.
raise_from(PyExc_TypeError, msg.c_str());
return nullptr;
}
#endif
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
@ -1123,13 +1111,11 @@ protected:
"Python type! The signature was\n\t";
msg += it->signature;
append_note_if_missing_header_is_suspected(msg);
#if PY_VERSION_HEX >= 0x03030000
// Attach additional error info to the exception if supported
if (PyErr_Occurred()) {
raise_from(PyExc_TypeError, msg.c_str());
return nullptr;
}
#endif
PyErr_SetString(PyExc_TypeError, msg.c_str());
return nullptr;
}
@ -1149,11 +1135,7 @@ public:
/// Create a new top-level Python module with the given name and docstring
PYBIND11_DEPRECATED("Use PYBIND11_MODULE or module_::create_extension_module instead")
explicit module_(const char *name, const char *doc = nullptr) {
#if PY_MAJOR_VERSION >= 3
*this = create_extension_module(name, doc, new PyModuleDef());
#else
*this = create_extension_module(name, doc, nullptr);
#endif
}
/** \rst
@ -1231,20 +1213,14 @@ public:
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */);
}
#if PY_MAJOR_VERSION >= 3
using module_def = PyModuleDef;
#else
struct module_def {};
#endif
/** \rst
Create a new top-level module that can be used as the main module of a C extension.
For Python 3, ``def`` should point to a statically allocated module_def.
For Python 2, ``def`` can be a nullptr and is completely ignored.
``def`` should point to a statically allocated module_def.
\endrst */
static module_ create_extension_module(const char *name, const char *doc, module_def *def) {
#if PY_MAJOR_VERSION >= 3
// module_def is PyModuleDef
// Placement new (not an allocation).
def = new (def)
@ -1258,12 +1234,6 @@ public:
/* m_clear */ nullptr,
/* m_free */ nullptr};
auto *m = PyModule_Create(def);
#else
// Ignore module_def *def; only necessary for Python 3
(void) def;
auto m = Py_InitModule3(
name, nullptr, options::show_user_defined_docstrings() ? doc : nullptr);
#endif
if (m == nullptr) {
if (PyErr_Occurred()) {
throw error_already_set();
@ -1290,14 +1260,12 @@ inline dict globals() {
return reinterpret_borrow<dict>(p ? p : module_::import("__main__").attr("__dict__").ptr());
}
#if PY_VERSION_HEX >= 0x03030000
template <typename... Args, typename = detail::enable_if_t<args_are_all_keyword_or_ds<Args...>()>>
PYBIND11_DEPRECATED("make_simple_namespace should be replaced with "
"py::module_::import(\"types\").attr(\"SimpleNamespace\") ")
object make_simple_namespace(Args &&...args_) {
return module_::import("types").attr("SimpleNamespace")(std::forward<Args>(args_)...);
}
#endif
PYBIND11_NAMESPACE_BEGIN(detail)
/// Generic support for creating new Python heap types
@ -2173,9 +2141,6 @@ public:
def_property_readonly("value", [](Type value) { return (Scalar) value; });
def("__int__", [](Type value) { return (Scalar) value; });
def("__index__", [](Type value) { return (Scalar) value; });
#if PY_MAJOR_VERSION < 3
def("__long__", [](Type value) { return (Scalar) value; });
#endif
attr("__setstate__") = cpp_function(
[](detail::value_and_holder &v_h, Scalar arg) {
detail::initimpl::setstate<Base>(

View File

@ -434,8 +434,6 @@ private:
# pragma warning(pop)
#endif
#if PY_VERSION_HEX >= 0x03030000
/// Replaces the current Python error indicator with the chosen error, performing a
/// 'raise from' to indicate that the chosen error was caused by the original error.
inline void raise_from(PyObject *type, const char *message) {
@ -473,8 +471,6 @@ inline void raise_from(error_already_set &err, PyObject *type, const char *messa
raise_from(type, message);
}
#endif
/** \defgroup python_builtins const_name
Unless stated otherwise, the following C++ functions behave the same
as their Python counterparts.
@ -591,12 +587,9 @@ inline ssize_t hash(handle obj) {
PYBIND11_NAMESPACE_BEGIN(detail)
inline handle get_function(handle value) {
if (value) {
#if PY_MAJOR_VERSION >= 3
if (PyInstanceMethod_Check(value.ptr())) {
value = PyInstanceMethod_GET_FUNCTION(value.ptr());
} else
#endif
if (PyMethod_Check(value.ptr())) {
} else if (PyMethod_Check(value.ptr())) {
value = PyMethod_GET_FUNCTION(value.ptr());
}
}
@ -608,7 +601,6 @@ inline handle get_function(handle value) {
// copied from cpython _PyDict_GetItemStringWithError
inline PyObject *dict_getitemstring(PyObject *v, const char *key) {
#if PY_MAJOR_VERSION >= 3
PyObject *kv = nullptr, *rv = nullptr;
kv = PyUnicode_FromString(key);
if (kv == NULL) {
@ -621,21 +613,14 @@ inline PyObject *dict_getitemstring(PyObject *v, const char *key) {
throw error_already_set();
}
return rv;
#else
return PyDict_GetItemString(v, key);
#endif
}
inline PyObject *dict_getitem(PyObject *v, PyObject *key) {
#if PY_MAJOR_VERSION >= 3
PyObject *rv = PyDict_GetItemWithError(v, key);
if (rv == NULL && PyErr_Occurred()) {
throw error_already_set();
}
return rv;
#else
return PyDict_GetItem(v, key);
#endif
}
// Helper aliases/functions to support implicit casting of values given to python
@ -1273,13 +1258,6 @@ private:
/// Return string representation -- always returns a new reference, even if already a str
static PyObject *raw_str(PyObject *op) {
PyObject *str_value = PyObject_Str(op);
#if PY_MAJOR_VERSION < 3
if (!str_value)
throw error_already_set();
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
Py_XDECREF(str_value);
str_value = unicode;
#endif
return str_value;
}
};
@ -1459,11 +1437,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
// unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes).
template <typename Unsigned>
Unsigned as_unsigned(PyObject *o) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(Unsigned) <= sizeof(unsigned long))
#if PY_VERSION_HEX < 0x03000000
|| PyInt_Check(o)
#endif
) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(Unsigned) <= sizeof(unsigned long))) {
unsigned long v = PyLong_AsUnsignedLong(o);
return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
}
@ -1922,7 +1896,6 @@ public:
return memoryview::from_buffer(const_cast<T *>(ptr), shape, strides, true);
}
#if PY_MAJOR_VERSION >= 3
/** \rst
Creates ``memoryview`` from static memory.
@ -1930,8 +1903,6 @@ public:
managed by Python. The caller is responsible for managing the lifetime
of ``mem``, which MUST outlive the memoryview constructed here.
This method is not available in Python 2.
See also: Python C API documentation for `PyMemoryView_FromBuffer`_.
.. _PyMemoryView_FromMemory:
@ -1950,12 +1921,10 @@ public:
return memoryview::from_memory(const_cast<void *>(mem), size, true);
}
# ifdef PYBIND11_HAS_STRING_VIEW
#ifdef PYBIND11_HAS_STRING_VIEW
static memoryview from_memory(std::string_view mem) {
return from_memory(const_cast<char *>(mem.data()), static_cast<ssize_t>(mem.size()), true);
}
# endif
#endif
};
@ -2010,11 +1979,7 @@ inline size_t len(handle h) {
/// Get the length hint of a Python object.
/// Returns 0 when this cannot be determined.
inline size_t len_hint(handle h) {
#if PY_VERSION_HEX >= 0x03040000
ssize_t result = PyObject_LengthHint(h.ptr(), 0);
#else
ssize_t result = PyObject_Length(h.ptr());
#endif
if (result < 0) {
// Sometimes a length can't be determined at all (eg generators)
// In which case simply return 0
@ -2029,13 +1994,6 @@ inline str repr(handle h) {
if (!str_value) {
throw error_already_set();
}
#if PY_MAJOR_VERSION < 3
PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr);
Py_XDECREF(str_value);
str_value = unicode;
if (!str_value)
throw error_already_set();
#endif
return reinterpret_steal<str>(str_value);
}

View File

@ -2,7 +2,7 @@ import nox
nox.options.sessions = ["lint", "tests", "tests_packaging"]
PYTHON_VERISONS = ["2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
PYTHON_VERISONS = ["3.5", "3.6", "3.7", "3.8", "3.9", "3.10", "3.11"]
@nox.session(reuse_venv=True)

View File

@ -1,4 +1,9 @@
# -*- coding: utf-8 -*-
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."
raise ImportError(msg)
from ._version import __version__, version_info
from .commands import get_cmake_dir, get_include

View File

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import sys
import sysconfig
@ -8,8 +5,7 @@ import sysconfig
from .commands import get_cmake_dir, get_include
def print_includes():
# type: () -> None
def print_includes() -> None:
dirs = [
sysconfig.get_path("include"),
sysconfig.get_path("platinclude"),
@ -25,8 +21,7 @@ def print_includes():
print(" ".join("-I" + d for d in unique_dirs))
def main():
# type: () -> None
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
from typing import Union
def _to_int(s):
def _to_int(s: str) -> Union[int, str]:
try:
return int(s)
except ValueError:

View File

@ -1,6 +0,0 @@
from typing import Tuple, Union
def _to_int(s: str) -> Union[int, str]: ...
__version__: str
version_info: Tuple[Union[int, str], ...]

View File

@ -1,18 +1,15 @@
# -*- coding: utf-8 -*-
import os
DIR = os.path.abspath(os.path.dirname(__file__))
def get_include(user=False):
# type: (bool) -> str
def get_include(user: bool = False) -> str:
installed_path = os.path.join(DIR, "include")
source_path = os.path.join(os.path.dirname(DIR), "include")
return installed_path if os.path.exists(installed_path) else source_path
def get_cmake_dir():
# type: () -> str
def get_cmake_dir() -> str:
cmake_installed_path = os.path.join(DIR, "share", "cmake", "pybind11")
if os.path.exists(cmake_installed_path):
return cmake_installed_path

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
"""
This module provides helpers for C++11+ projects using pybind11.
@ -49,6 +47,20 @@ import sysconfig
import tempfile
import threading
import warnings
from functools import lru_cache
from pathlib import Path
from typing import (
Any,
Callable,
Dict,
Iterable,
Iterator,
List,
Optional,
Tuple,
TypeVar,
Union,
)
try:
from setuptools import Extension as _Extension
@ -61,7 +73,6 @@ import distutils.ccompiler
import distutils.errors
WIN = sys.platform.startswith("win32") and "mingw" not in sysconfig.get_platform()
PY2 = sys.version_info[0] < 3
MACOS = sys.platform.startswith("darwin")
STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
@ -73,7 +84,7 @@ STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
# directory into your path if it sits beside your setup.py.
class Pybind11Extension(_Extension):
class Pybind11Extension(_Extension): # type: ignore[misc]
"""
Build a C++11+ Extension module with pybind11. This automatically adds the
recommended flags when you init the extension and assumes C++ sources - you
@ -95,21 +106,18 @@ class Pybind11Extension(_Extension):
If you want to add pybind11 headers manually, for example for an exact
git checkout, then set ``include_pybind11=False``.
Warning: do not use property-based access to the instance on Python 2 -
this is an ugly old-style class due to Distutils.
"""
# flags are prepended, so that they can be further overridden, e.g. by
# ``extra_compile_args=["-g"]``.
def _add_cflags(self, flags):
def _add_cflags(self, flags: List[str]) -> None:
self.extra_compile_args[:0] = flags
def _add_ldflags(self, flags):
def _add_ldflags(self, flags: List[str]) -> None:
self.extra_link_args[:0] = flags
def __init__(self, *args, **kwargs):
def __init__(self, *args: Any, **kwargs: Any) -> None:
self._cxx_level = 0
cxx_std = kwargs.pop("cxx_std", 0)
@ -119,9 +127,7 @@ class Pybind11Extension(_Extension):
include_pybind11 = kwargs.pop("include_pybind11", True)
# Can't use super here because distutils has old-style classes in
# Python 2!
_Extension.__init__(self, *args, **kwargs)
super().__init__(*args, **kwargs)
# Include the installed package pybind11 headers
if include_pybind11:
@ -133,11 +139,10 @@ class Pybind11Extension(_Extension):
if pyinc not in self.include_dirs:
self.include_dirs.append(pyinc)
except ImportError:
except ModuleNotFoundError:
pass
# Have to use the accessor manually to support Python 2 distutils
Pybind11Extension.cxx_std.__set__(self, cxx_std)
self.cxx_std = cxx_std
cflags = []
ldflags = []
@ -157,18 +162,18 @@ class Pybind11Extension(_Extension):
self._add_ldflags(ldflags)
@property
def cxx_std(self):
def cxx_std(self) -> int:
"""
The CXX standard level. If set, will add the required flags. If left
at 0, it will trigger an automatic search when pybind11's build_ext
is used. If None, will have no effect. Besides just the flags, this
may add a register warning/error fix for Python 2 or macos-min 10.9
or 10.14.
The CXX standard level. If set, will add the required flags. If left at
0, it will trigger an automatic search when pybind11's build_ext is
used. If None, will have no effect. Besides just the flags, this may
add a macos-min 10.9 or 10.14 flag if MACOSX_DEPLOYMENT_TARGET is
unset.
"""
return self._cxx_level
@cxx_std.setter
def cxx_std(self, level):
def cxx_std(self, level: int) -> None:
if self._cxx_level:
warnings.warn("You cannot safely change the cxx_level after setting it!")
@ -195,31 +200,20 @@ class Pybind11Extension(_Extension):
current_macos = tuple(int(x) for x in platform.mac_ver()[0].split(".")[:2])
desired_macos = (10, 9) if level < 17 else (10, 14)
macos_string = ".".join(str(x) for x in min(current_macos, desired_macos))
macosx_min = "-mmacosx-version-min=" + macos_string
macosx_min = "-mmacosx-version-min={}".format(macos_string)
cflags += [macosx_min]
ldflags += [macosx_min]
if PY2:
if WIN:
# Will be ignored on MSVC 2015, where C++17 is not supported so
# this flag is not valid.
cflags += ["/wd5033"]
elif level >= 17:
cflags += ["-Wno-register"]
elif level >= 14:
cflags += ["-Wno-deprecated-register"]
self._add_cflags(cflags)
self._add_ldflags(ldflags)
# Just in case someone clever tries to multithread
tmp_chdir_lock = threading.Lock()
cpp_cache_lock = threading.Lock()
@contextlib.contextmanager
def tmp_chdir():
def tmp_chdir() -> Iterator[str]:
"Prepare and enter a temporary directory, cleanup when done"
# Threadsafe
@ -235,7 +229,7 @@ def tmp_chdir():
# cf http://bugs.python.org/issue26689
def has_flag(compiler, flag):
def has_flag(compiler: Any, flag: str) -> bool:
"""
Return the flag if a flag name is supported on the
specified compiler, otherwise None (can be used as a boolean).
@ -243,13 +237,12 @@ def has_flag(compiler, flag):
"""
with tmp_chdir():
fname = "flagcheck.cpp"
with open(fname, "w") as f:
fname = Path("flagcheck.cpp")
# Don't trigger -Wunused-parameter.
f.write("int main (int, char **) { return 0; }")
fname.write_text("int main (int, char **) { return 0; }")
try:
compiler.compile([fname], extra_postargs=[flag])
compiler.compile([str(fname)], extra_postargs=[flag])
except distutils.errors.CompileError:
return False
return True
@ -259,7 +252,8 @@ def has_flag(compiler, flag):
cpp_flag_cache = None
def auto_cpp_level(compiler):
@lru_cache()
def auto_cpp_level(compiler: Any) -> Union[str, int]:
"""
Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows.
"""
@ -267,48 +261,38 @@ def auto_cpp_level(compiler):
if WIN:
return "latest"
global cpp_flag_cache
# If this has been previously calculated with the same args, return that
with cpp_cache_lock:
if cpp_flag_cache:
return cpp_flag_cache
levels = [17, 14, 11]
for level in levels:
if has_flag(compiler, STD_TMPL.format(level)):
with cpp_cache_lock:
cpp_flag_cache = level
return level
msg = "Unsupported compiler -- at least C++11 support is needed!"
raise RuntimeError(msg)
class build_ext(_build_ext): # noqa: N801
class build_ext(_build_ext): # type: ignore[misc] # noqa: N801
"""
Customized build_ext that allows an auto-search for the highest supported
C++ level for Pybind11Extension. This is only needed for the auto-search
for now, and is completely optional otherwise.
"""
def build_extensions(self):
def build_extensions(self) -> None:
"""
Build extensions, injecting C++ std for Pybind11Extension if needed.
"""
for ext in self.extensions:
if hasattr(ext, "_cxx_level") and ext._cxx_level == 0:
# Python 2 syntax - old-style distutils class
ext.__class__.cxx_std.__set__(ext, auto_cpp_level(self.compiler))
ext.cxx_std = auto_cpp_level(self.compiler)
# Python 2 doesn't allow super here, since distutils uses old-style
# classes!
_build_ext.build_extensions(self)
super().build_extensions()
def intree_extensions(paths, package_dir=None):
def intree_extensions(
paths: Iterable[str], package_dir: Optional[Dict[str, str]] = None
) -> List[Pybind11Extension]:
"""
Generate Pybind11Extensions from source files directly located in a Python
source tree.
@ -318,6 +302,7 @@ def intree_extensions(paths, package_dir=None):
not contain an ``__init__.py`` file.
"""
exts = []
for path in paths:
if package_dir is None:
parent, _ = os.path.split(path)
@ -327,24 +312,25 @@ def intree_extensions(paths, package_dir=None):
qualified_name = relname.replace(os.path.sep, ".")
exts.append(Pybind11Extension(qualified_name, [path]))
else:
found = False
for prefix, parent in package_dir.items():
if path.startswith(parent):
found = True
relname, _ = os.path.splitext(os.path.relpath(path, parent))
qualified_name = relname.replace(os.path.sep, ".")
if prefix:
qualified_name = prefix + "." + qualified_name
exts.append(Pybind11Extension(qualified_name, [path]))
if not found:
raise ValueError(
"path {} is not a child of any of the directories listed "
"in 'package_dir' ({})".format(path, package_dir)
)
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)
raise ValueError(msg)
return exts
def naive_recompile(obj, src):
def naive_recompile(obj: str, src: str) -> bool:
"""
This will recompile only if the source file changes. It does not check
header files, so a more advanced function or Ccache is better if you have
@ -353,7 +339,7 @@ def naive_recompile(obj, src):
return os.stat(obj).st_mtime < os.stat(src).st_mtime
def no_recompile(obg, src):
def no_recompile(obg: str, src: str) -> bool:
"""
This is the safest but slowest choice (and is the default) - will always
recompile sources.
@ -361,15 +347,33 @@ def no_recompile(obg, src):
return True
S = TypeVar("S", bound="ParallelCompile")
CCompilerMethod = Callable[
[
distutils.ccompiler.CCompiler,
List[str],
Optional[str],
Optional[Union[Tuple[str], Tuple[str, Optional[str]]]],
Optional[List[str]],
bool,
Optional[List[str]],
Optional[List[str]],
Optional[List[str]],
],
List[str],
]
# Optional parallel compile utility
# inspired by: http://stackoverflow.com/questions/11013851/speeding-up-build-process-with-distutils
# and: https://github.com/tbenthompson/cppimport/blob/stable/cppimport/build_module.py
# and NumPy's parallel distutils module:
# https://github.com/numpy/numpy/blob/master/numpy/distutils/ccompiler.py
class ParallelCompile(object):
class ParallelCompile:
"""
Make a parallel compile function. Inspired by
numpy.distutils.ccompiler.CCompiler_compile and cppimport.
numpy.distutils.ccompiler.CCompiler.compile and cppimport.
This takes several arguments that allow you to customize the compile
function created:
@ -404,35 +408,41 @@ class ParallelCompile(object):
__slots__ = ("envvar", "default", "max", "_old", "needs_recompile")
def __init__(self, envvar=None, default=0, max=0, needs_recompile=no_recompile):
def __init__(
self,
envvar: Optional[str] = None,
default: int = 0,
max: int = 0,
needs_recompile: Callable[[str, str], bool] = no_recompile,
) -> None:
self.envvar = envvar
self.default = default
self.max = max
self.needs_recompile = needs_recompile
self._old = []
self._old = [] # type: List[CCompilerMethod]
def function(self):
def function(self) -> CCompilerMethod:
"""
Builds a function object usable as distutils.ccompiler.CCompiler.compile.
"""
def compile_function(
compiler,
sources,
output_dir=None,
macros=None,
include_dirs=None,
debug=0,
extra_preargs=None,
extra_postargs=None,
depends=None,
):
compiler: distutils.ccompiler.CCompiler,
sources: List[str],
output_dir: Optional[str] = None,
macros: Optional[Union[Tuple[str], Tuple[str, Optional[str]]]] = None,
include_dirs: Optional[List[str]] = None,
debug: bool = False,
extra_preargs: Optional[List[str]] = None,
extra_postargs: Optional[List[str]] = None,
depends: Optional[List[str]] = None,
) -> Any:
# These lines are directly from distutils.ccompiler.CCompiler
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile(
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile( # type: ignore[attr-defined]
output_dir, macros, include_dirs, sources, depends, extra_postargs
)
cc_args = compiler._get_cc_args(pp_opts, debug, extra_preargs)
cc_args = compiler._get_cc_args(pp_opts, debug, extra_preargs) # type: ignore[attr-defined]
# The number of threads; start with default.
threads = self.default
@ -441,14 +451,14 @@ class ParallelCompile(object):
if self.envvar is not None:
threads = int(os.environ.get(self.envvar, self.default))
def _single_compile(obj):
def _single_compile(obj: Any) -> None:
try:
src, ext = build[obj]
except KeyError:
return
if not os.path.exists(obj) or self.needs_recompile(obj, src):
compiler._compile(obj, src, ext, cc_args, extra_postargs, pp_opts)
compiler._compile(obj, src, ext, cc_args, extra_postargs, pp_opts) # type: ignore[attr-defined]
try:
# Importing .synchronize checks for platforms that have some multiprocessing
@ -466,14 +476,9 @@ class ParallelCompile(object):
threads = 1
if threads > 1:
pool = ThreadPool(threads)
# In Python 2, ThreadPool can't be used as a context manager.
# Once we are no longer supporting it, this can be 'with pool:'
try:
with ThreadPool(threads) as pool:
for _ in pool.imap_unordered(_single_compile, objects):
pass
finally:
pool.terminate()
else:
for ob in objects:
_single_compile(ob)
@ -482,13 +487,13 @@ class ParallelCompile(object):
return compile_function
def install(self):
distutils.ccompiler.CCompiler.compile = self.function()
def install(self: S) -> S:
distutils.ccompiler.CCompiler.compile = self.function() # type: ignore[assignment]
return self
def __enter__(self):
def __enter__(self: S) -> S:
self._old.append(distutils.ccompiler.CCompiler.compile)
return self.install()
def __exit__(self, *args):
distutils.ccompiler.CCompiler.compile = self._old.pop()
def __exit__(self, *args: Any) -> None:
distutils.ccompiler.CCompiler.compile = self._old.pop() # type: ignore[assignment]

View File

@ -1,63 +0,0 @@
# IMPORTANT: Should stay in sync with setup_helpers.py (mostly checked by CI /
# pre-commit).
import contextlib
import distutils.ccompiler
from distutils.command.build_ext import build_ext as _build_ext # type: ignore
from distutils.extension import Extension as _Extension
from types import TracebackType
from typing import Any, Callable, Dict, Iterator, List, Optional, Type, TypeVar, Union
WIN: bool
PY2: bool
MACOS: bool
STD_TMPL: str
class Pybind11Extension(_Extension):
def _add_cflags(self, *flags: str) -> None: ...
def _add_lflags(self, *flags: str) -> None: ...
def __init__(
self, *args: Any, cxx_std: int = 0, language: str = "c++", **kwargs: Any
) -> None: ...
@property
def cxx_std(self) -> int: ...
@cxx_std.setter
def cxx_std(self, level: int) -> None: ...
@contextlib.contextmanager
def tmp_chdir() -> Iterator[str]: ...
def has_flag(compiler: distutils.ccompiler.CCompiler, flag: str) -> bool: ...
def auto_cpp_level(compiler: distutils.ccompiler.CCompiler) -> Union[int, str]: ...
class build_ext(_build_ext): # type: ignore
def build_extensions(self) -> None: ...
def intree_extensions(
paths: Iterator[str], package_dir: Optional[Dict[str, str]] = None
) -> List[Pybind11Extension]: ...
def no_recompile(obj: str, src: str) -> bool: ...
def naive_recompile(obj: str, src: str) -> bool: ...
T = TypeVar("T", bound="ParallelCompile")
class ParallelCompile:
envvar: Optional[str]
default: int
max: int
needs_recompile: Callable[[str, str], bool]
def __init__(
self,
envvar: Optional[str] = None,
default: int = 0,
max: int = 0,
needs_recompile: Callable[[str, str], bool] = no_recompile,
) -> None: ...
def function(self) -> Any: ...
def install(self: T) -> T: ...
def __enter__(self: T) -> T: ...
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
exc_value: Optional[BaseException],
traceback: Optional[TracebackType],
) -> None: ...

View File

@ -22,20 +22,11 @@ known_first_party = "env,pybind11_cross_module_tests,pybind11_tests,"
profile = "black"
[tool.mypy]
files = "pybind11"
python_version = "2.7"
files = ["pybind11"]
python_version = "3.6"
warn_unused_configs = true
strict = true
disallow_any_generics = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
disallow_incomplete_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
no_implicit_reexport = true
strict_equality = true
[[tool.mypy.overrides]]
module = ["ghapi.*", "setuptools.*"]
ignore_missing_imports = true

View File

@ -13,8 +13,7 @@ classifiers =
Topic :: Software Development :: Libraries :: Python Modules
Topic :: Utilities
Programming Language :: C++
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
@ -39,15 +38,12 @@ project_urls =
Chat = https://gitter.im/pybind/Lobby
[options]
python_requires = >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
python_requires = >=3.5
zip_safe = False
[bdist_wheel]
universal=1
[flake8]
max-line-length = 99
max-line-length = 120
show_source = True
exclude = .git, __pycache__, build, dist, docs, tools, venv
ignore =

View File

@ -1,36 +1,36 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Setup script for PyPI; use CMakeFile.txt to build extension modules
import contextlib
import io
import os
import re
import shutil
import string
import subprocess
import sys
import tempfile
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Dict, Iterator, List, Union
import setuptools.command.sdist
DIR = os.path.abspath(os.path.dirname(__file__))
DIR = Path(__file__).parent.absolute()
VERSION_REGEX = re.compile(
r"^\s*#\s*define\s+PYBIND11_VERSION_([A-Z]+)\s+(.*)$", re.MULTILINE
)
VERSION_FILE = Path("pybind11/_version.py")
COMMON_FILE = Path("include/pybind11/detail/common.h")
def build_expected_version_hex(matches):
def build_expected_version_hex(matches: Dict[str, str]) -> str:
patch_level_serial = matches["PATCH"]
serial = None
try:
major = int(matches["MAJOR"])
minor = int(matches["MINOR"])
flds = patch_level_serial.split(".")
if flds:
patch = int(flds[0])
level = None
if len(flds) == 1:
level = "0"
serial = 0
@ -40,17 +40,13 @@ def build_expected_version_hex(matches):
if level_serial.startswith(level):
serial = int(level_serial[len(level) :])
break
except ValueError:
pass
if serial is None:
msg = 'Invalid PYBIND11_VERSION_PATCH: "{}"'.format(patch_level_serial)
raise RuntimeError(msg)
return (
"0x"
+ "{:02x}{:02x}{:02x}{}{:x}".format(
version_hex_str = "{:02x}{:02x}{:02x}{}{:x}".format(
major, minor, patch, level[:1], serial
).upper()
)
return "0x{}".format(version_hex_str.upper())
# PYBIND11_GLOBAL_SDIST will build a different sdist, with the python-headers
@ -58,24 +54,25 @@ def build_expected_version_hex(matches):
global_sdist = os.environ.get("PYBIND11_GLOBAL_SDIST", False)
setup_py = "tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
setup_py = Path(
"tools/setup_global.py.in" if global_sdist else "tools/setup_main.py.in"
)
extra_cmd = 'cmdclass["sdist"] = SDist\n'
to_src = (
("pyproject.toml", "tools/pyproject.toml"),
("setup.py", setup_py),
(Path("pyproject.toml"), Path("tools/pyproject.toml")),
(Path("setup.py"), setup_py),
)
# Read the listed version
with open("pybind11/_version.py") as f:
code = compile(f.read(), "pybind11/_version.py", "exec")
loc = {}
loc = {} # type: Dict[str, str]
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
exec(code, loc)
version = loc["__version__"]
# Verify that the version matches the one in C++
with io.open("include/pybind11/detail/common.h", encoding="utf8") as f:
matches = dict(VERSION_REGEX.findall(f.read()))
matches = dict(VERSION_REGEX.findall(COMMON_FILE.read_text(encoding="utf8")))
cpp_version = "{MAJOR}.{MINOR}.{PATCH}".format(**matches)
if version != cpp_version:
msg = "Python version {} does not match C++ version {}!".format(
@ -84,56 +81,44 @@ if version != cpp_version:
raise RuntimeError(msg)
version_hex = matches.get("HEX", "MISSING")
expected_version_hex = build_expected_version_hex(matches)
if version_hex != expected_version_hex:
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,
expected_version_hex,
version_hex, exp_version_hex
)
raise RuntimeError(msg)
def get_and_replace(filename, binary=False, **opts):
with open(filename, "rb" if binary else "r") as f:
contents = f.read()
# Replacement has to be done on text in Python 3 (both work in Python 2)
# TODO: use literals & overload (typing extensions or Python 3.8)
def get_and_replace(
filename: Path, binary: bool = False, **opts: str
) -> Union[bytes, str]:
if binary:
contents = filename.read_bytes()
return string.Template(contents.decode()).substitute(opts).encode()
else:
return string.Template(contents).substitute(opts)
return string.Template(filename.read_text()).substitute(opts)
# Use our input files instead when making the SDist (and anything that depends
# on it, like a wheel)
class SDist(setuptools.command.sdist.sdist):
def make_release_tree(self, base_dir, files):
setuptools.command.sdist.sdist.make_release_tree(self, base_dir, files)
class SDist(setuptools.command.sdist.sdist): # type: ignore[misc]
def make_release_tree(self, base_dir: str, files: List[str]) -> None:
super().make_release_tree(base_dir, files)
for to, src in to_src:
txt = get_and_replace(src, binary=True, version=version, extra_cmd="")
dest = os.path.join(base_dir, to)
dest = Path(base_dir) / to
# This is normally linked, so unlink before writing!
os.unlink(dest)
with open(dest, "wb") as f:
f.write(txt)
# Backport from Python 3
@contextlib.contextmanager
def TemporaryDirectory(): # noqa: N802
"Prepare a temporary directory, cleanup when done"
try:
tmpdir = tempfile.mkdtemp()
yield tmpdir
finally:
shutil.rmtree(tmpdir)
dest.unlink()
dest.write_bytes(txt) # type: ignore[arg-type]
# Remove the CMake install directory when done
@contextlib.contextmanager
def remove_output(*sources):
def remove_output(*sources: str) -> Iterator[None]:
try:
yield
finally:
@ -156,9 +141,14 @@ with remove_output("pybind11/include", "pybind11/share"):
if "DCMAKE_INSTALL_PREFIX" not in c
]
cmd += fcommand
cmake_opts = dict(cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
subprocess.check_call(cmd, **cmake_opts)
subprocess.check_call(["cmake", "--install", tmpdir], **cmake_opts)
subprocess.run(cmd, check=True, cwd=DIR, stdout=sys.stdout, stderr=sys.stderr)
subprocess.run(
["cmake", "--install", tmpdir],
check=True,
cwd=DIR,
stdout=sys.stdout,
stderr=sys.stderr,
)
txt = get_and_replace(setup_py, version=version, extra_cmd=extra_cmd)
code = compile(txt, setup_py, "exec")

View File

@ -179,11 +179,6 @@ if(PYBIND11_TEST_FILTER)
pybind11_filter_tests(PYBIND11_TEST_FILES ${PYBIND11_TEST_FILTER})
endif()
if(PYTHON_VERSION VERSION_LESS 3.5)
pybind11_filter_tests(PYBIND11_TEST_FILES test_async.cpp MESSAGE
"Skipping test_async on Python 2")
endif()
# Skip tests for CUDA check:
# /pybind11/tests/test_constants_and_functions.cpp(125):
# error: incompatible exception specifications
@ -388,17 +383,6 @@ function(pybind11_enable_warnings target_name)
-diag-disable 11074,11076)
endif()
endif()
# Needs to be re-added since the ordering requires these to be after the ones above
if(CMAKE_CXX_STANDARD
AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"
AND PYTHON_VERSION VERSION_LESS 3.0)
if(CMAKE_CXX_STANDARD LESS 17)
target_compile_options(${target_name} PUBLIC -Wno-deprecated-register)
else()
target_compile_options(${target_name} PUBLIC -Wno-register)
endif()
endif()
endfunction()
set(test_targets pybind11_tests)

View File

@ -1,8 +1,7 @@
# -*- coding: utf-8 -*-
"""pytest configuration
Extends output capture as needed by pybind11: ignore constructors, optional unordered lines.
Adds docstring and exceptions message sanitizers: ignore Python 2 vs 3 differences.
Adds docstring and exceptions message sanitizers.
"""
import contextlib
@ -13,19 +12,14 @@ import textwrap
import pytest
import env
# Early diagnostic for failed imports
import pybind11_tests # noqa: F401
_unicode_marker = re.compile(r"u(\'[^\']*\')")
_long_marker = re.compile(r"([0-9])L")
_hexadecimal = re.compile(r"0x[0-9a-fA-F]+")
# Avoid collecting Python3 only files
collect_ignore = []
if env.PY2:
collect_ignore.append("test_async.py")
def _strip_and_dedent(s):
@ -45,7 +39,7 @@ def _make_explanation(a, b):
]
class Output(object):
class Output:
"""Basic output post-processing and comparison"""
def __init__(self, string):
@ -83,7 +77,7 @@ class Unordered(Output):
return False
class Capture(object):
class Capture:
def __init__(self, capfd):
self.capfd = capfd
self.out = ""
@ -126,7 +120,7 @@ def capture(capsys):
return Capture(capsys)
class SanitizedString(object):
class SanitizedString:
def __init__(self, sanitizer):
self.sanitizer = sanitizer
self.string = ""
@ -149,9 +143,7 @@ class SanitizedString(object):
def _sanitize_general(s):
s = s.strip()
s = s.replace("pybind11_tests.", "m.")
s = s.replace("unicode", "str")
s = _long_marker.sub(r"\1", s)
s = _unicode_marker.sub(r"\1", s)
return s

View File

@ -25,31 +25,14 @@ void gil_acquire() { py::gil_scoped_acquire gil; }
constexpr char kModuleName[] = "cross_module_gil_utils";
#if PY_MAJOR_VERSION >= 3
struct PyModuleDef moduledef
= {PyModuleDef_HEAD_INIT, kModuleName, NULL, 0, NULL, NULL, NULL, NULL, NULL};
#else
PyMethodDef module_methods[] = {{NULL, NULL, 0, NULL}};
#endif
} // namespace
extern "C" PYBIND11_EXPORT
#if PY_MAJOR_VERSION >= 3
PyObject *
PyInit_cross_module_gil_utils()
#else
void
initcross_module_gil_utils()
#endif
{
extern "C" PYBIND11_EXPORT PyObject *PyInit_cross_module_gil_utils() {
PyObject *m =
#if PY_MAJOR_VERSION >= 3
PyModule_Create(&moduledef);
#else
Py_InitModule(kModuleName, module_methods);
#endif
PyObject *m = PyModule_Create(&moduledef);
if (m != NULL) {
static_assert(sizeof(&gil_acquire) == sizeof(void *),
@ -58,7 +41,5 @@ extern "C" PYBIND11_EXPORT
m, "gil_acquire_funcaddr", PyLong_FromVoidPtr(reinterpret_cast<void *>(&gil_acquire)));
}
#if PY_MAJOR_VERSION >= 3
return m;
#endif
}

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import platform
import sys
@ -11,10 +10,6 @@ WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
CPYTHON = platform.python_implementation() == "CPython"
PYPY = platform.python_implementation() == "PyPy"
PY2 = sys.version_info.major == 2
PY = sys.version_info
def deprecated_call():
"""

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import contextlib
import os
import string
@ -64,11 +63,9 @@ py_files = {
"__init__.py",
"__main__.py",
"_version.py",
"_version.pyi",
"commands.py",
"py.typed",
"setup_helpers.py",
"setup_helpers.pyi",
}
headers = main_headers | detail_headers | stl_headers

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import os
import subprocess
import sys
@ -19,7 +18,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
(tmpdir / "setup.py").write_text(
dedent(
u"""\
"""\
import sys
sys.path.append({MAIN_DIR!r})
@ -58,7 +57,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
(tmpdir / "main.cpp").write_text(
dedent(
u"""\
"""\
#include <pybind11/pybind11.h>
int f(int x) {
@ -96,7 +95,7 @@ def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
(tmpdir / "test.py").write_text(
dedent(
u"""\
"""\
import simple_setup
assert simple_setup.f(3) == 9
"""
@ -121,10 +120,11 @@ def test_intree_extensions(monkeypatch, tmpdir):
subdir.ensure_dir()
src = subdir / "ext.cpp"
src.ensure()
(ext,) = intree_extensions([src.relto(tmpdir)])
relpath = src.relto(tmpdir)
(ext,) = intree_extensions([relpath])
assert ext.name == "ext"
subdir.ensure("__init__.py")
(ext,) = intree_extensions([src.relto(tmpdir)])
(ext,) = intree_extensions([relpath])
assert ext.name == "dir.ext"

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
asyncio = pytest.importorskip("asyncio")

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import ctypes
import io
import struct
@ -93,16 +92,16 @@ def test_pointer_to_member_fn():
def test_readonly_buffer():
buf = m.BufferReadOnly(0x64)
view = memoryview(buf)
assert view[0] == b"d" if env.PY2 else 0x64
assert view[0] == 0x64
assert view.readonly
with pytest.raises(TypeError):
view[0] = b"\0" if env.PY2 else 0
view[0] = 0
def test_selective_readonly_buffer():
buf = m.BufferReadOnlySelect()
memoryview(buf)[0] = b"d" if env.PY2 else 0x64
memoryview(buf)[0] = 0x64
assert buf.value == 0x64
io.BytesIO(b"A").readinto(buf)
@ -110,7 +109,7 @@ def test_selective_readonly_buffer():
buf.readonly = True
with pytest.raises(TypeError):
memoryview(buf)[0] = b"\0" if env.PY2 else 0
memoryview(buf)[0] = 0
with pytest.raises(TypeError):
io.BytesIO(b"1").readinto(buf)
@ -145,9 +144,6 @@ def test_ctypes_array_2d():
assert not info.readonly
@pytest.mark.skipif(
"env.PYPY and env.PY2", reason="PyPy2 bytes buffer not reported as readonly"
)
def test_ctypes_from_buffer():
test_pystr = b"0123456789"
for pyarray in (test_pystr, bytearray(test_pystr)):

View File

@ -110,8 +110,7 @@ TEST_SUBMODULE(builtin_casters, m) {
"def");
});
m.def("bad_utf16_string", [=]() { return std::u16string({b16, char16_t(0xd800), z16}); });
#if PY_MAJOR_VERSION >= 3
// Under Python 2.7, invalid unicode UTF-32 characters don't appear to trigger
// Under Python 2.7, invalid unicode UTF-32 characters didn't appear to trigger
// UnicodeDecodeError
m.def("bad_utf32_string", [=]() { return std::u32string({a32, char32_t(0xd800), z32}); });
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) {
@ -119,7 +118,6 @@ TEST_SUBMODULE(builtin_casters, m) {
return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
});
}
#endif
m.def("u8_Z", []() -> char { return 'Z'; });
m.def("u8_eacute", []() -> char { return '\xe9'; });
m.def("u16_ibang", [=]() -> char16_t { return ib16; });
@ -198,12 +196,10 @@ TEST_SUBMODULE(builtin_casters, m) {
[]() { return [](py::str s) { return s; }("abc \342\200\275 def"sv); });
m.def("string_view_from_bytes",
[](const py::bytes &b) { return [](std::string_view s) { return s; }(b); });
# if PY_MAJOR_VERSION >= 3
m.def("string_view_memoryview", []() {
static constexpr auto val = "Have some \360\237\216\202"sv;
return py::memoryview::from_memory(val);
});
# endif
# ifdef PYBIND11_HAS_U8STRING
m.def("string_view8_print", [](std::u8string_view s) { py::print(s, s.size()); });

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import sys
import pytest
import env
@ -12,12 +13,12 @@ def test_simple_string():
def test_unicode_conversion():
"""Tests unicode conversion and error reporting."""
assert m.good_utf8_string() == u"Say utf8‽ 🎂 𝐀"
assert m.good_utf16_string() == u"b‽🎂𝐀z"
assert m.good_utf32_string() == u"a𝐀🎂‽z"
assert m.good_wchar_string() == u"a⸘𝐀z"
assert m.good_utf8_string() == "Say utf8‽ 🎂 𝐀"
assert m.good_utf16_string() == "b‽🎂𝐀z"
assert m.good_utf32_string() == "a𝐀🎂‽z"
assert m.good_wchar_string() == "a⸘𝐀z"
if hasattr(m, "has_u8string"):
assert m.good_utf8_u8string() == u"Say utf8‽ 🎂 𝐀"
assert m.good_utf8_u8string() == "Say utf8‽ 🎂 𝐀"
with pytest.raises(UnicodeDecodeError):
m.bad_utf8_string()
@ -25,7 +26,7 @@ def test_unicode_conversion():
with pytest.raises(UnicodeDecodeError):
m.bad_utf16_string()
# These are provided only if they actually fail (they don't when 32-bit and under Python 2.7)
# These are provided only if they actually fail (they don't when 32-bit)
if hasattr(m, "bad_utf32_string"):
with pytest.raises(UnicodeDecodeError):
m.bad_utf32_string()
@ -37,10 +38,10 @@ def test_unicode_conversion():
m.bad_utf8_u8string()
assert m.u8_Z() == "Z"
assert m.u8_eacute() == u"é"
assert m.u16_ibang() == u""
assert m.u32_mathbfA() == u"𝐀"
assert m.wchar_heart() == u""
assert m.u8_eacute() == "é"
assert m.u16_ibang() == ""
assert m.u32_mathbfA() == "𝐀"
assert m.wchar_heart() == ""
if hasattr(m, "has_u8string"):
assert m.u8_char8_Z() == "Z"
@ -53,68 +54,68 @@ def test_single_char_arguments():
toolong_message = "Expected a character, but multi-character string found"
assert m.ord_char(u"a") == 0x61 # simple ASCII
assert m.ord_char_lv(u"b") == 0x62
assert m.ord_char("a") == 0x61 # simple ASCII
assert m.ord_char_lv("b") == 0x62
assert (
m.ord_char(u"é") == 0xE9
m.ord_char("é") == 0xE9
) # requires 2 bytes in utf-8, but can be stuffed in a char
with pytest.raises(ValueError) as excinfo:
assert m.ord_char(u"Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
assert m.ord_char("Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
assert str(excinfo.value) == toobig_message(0x100)
with pytest.raises(ValueError) as excinfo:
assert m.ord_char(u"ab")
assert m.ord_char("ab")
assert str(excinfo.value) == toolong_message
assert m.ord_char16(u"a") == 0x61
assert m.ord_char16(u"é") == 0xE9
assert m.ord_char16_lv(u"ê") == 0xEA
assert m.ord_char16(u"Ā") == 0x100
assert m.ord_char16(u"") == 0x203D
assert m.ord_char16(u"") == 0x2665
assert m.ord_char16_lv(u"") == 0x2661
assert m.ord_char16("a") == 0x61
assert m.ord_char16("é") == 0xE9
assert m.ord_char16_lv("ê") == 0xEA
assert m.ord_char16("Ā") == 0x100
assert m.ord_char16("") == 0x203D
assert m.ord_char16("") == 0x2665
assert m.ord_char16_lv("") == 0x2661
with pytest.raises(ValueError) as excinfo:
assert m.ord_char16(u"🎂") == 0x1F382 # requires surrogate pair
assert m.ord_char16("🎂") == 0x1F382 # requires surrogate pair
assert str(excinfo.value) == toobig_message(0x10000)
with pytest.raises(ValueError) as excinfo:
assert m.ord_char16(u"aa")
assert m.ord_char16("aa")
assert str(excinfo.value) == toolong_message
assert m.ord_char32(u"a") == 0x61
assert m.ord_char32(u"é") == 0xE9
assert m.ord_char32(u"Ā") == 0x100
assert m.ord_char32(u"") == 0x203D
assert m.ord_char32(u"") == 0x2665
assert m.ord_char32(u"🎂") == 0x1F382
assert m.ord_char32("a") == 0x61
assert m.ord_char32("é") == 0xE9
assert m.ord_char32("Ā") == 0x100
assert m.ord_char32("") == 0x203D
assert m.ord_char32("") == 0x2665
assert m.ord_char32("🎂") == 0x1F382
with pytest.raises(ValueError) as excinfo:
assert m.ord_char32(u"aa")
assert m.ord_char32("aa")
assert str(excinfo.value) == toolong_message
assert m.ord_wchar(u"a") == 0x61
assert m.ord_wchar(u"é") == 0xE9
assert m.ord_wchar(u"Ā") == 0x100
assert m.ord_wchar(u"") == 0x203D
assert m.ord_wchar(u"") == 0x2665
assert m.ord_wchar("a") == 0x61
assert m.ord_wchar("é") == 0xE9
assert m.ord_wchar("Ā") == 0x100
assert m.ord_wchar("") == 0x203D
assert m.ord_wchar("") == 0x2665
if m.wchar_size == 2:
with pytest.raises(ValueError) as excinfo:
assert m.ord_wchar(u"🎂") == 0x1F382 # requires surrogate pair
assert m.ord_wchar("🎂") == 0x1F382 # requires surrogate pair
assert str(excinfo.value) == toobig_message(0x10000)
else:
assert m.ord_wchar(u"🎂") == 0x1F382
assert m.ord_wchar("🎂") == 0x1F382
with pytest.raises(ValueError) as excinfo:
assert m.ord_wchar(u"aa")
assert m.ord_wchar("aa")
assert str(excinfo.value) == toolong_message
if hasattr(m, "has_u8string"):
assert m.ord_char8(u"a") == 0x61 # simple ASCII
assert m.ord_char8_lv(u"b") == 0x62
assert m.ord_char8("a") == 0x61 # simple ASCII
assert m.ord_char8_lv("b") == 0x62
assert (
m.ord_char8(u"é") == 0xE9
m.ord_char8("é") == 0xE9
) # requires 2 bytes in utf-8, but can be stuffed in a char
with pytest.raises(ValueError) as excinfo:
assert m.ord_char8(u"Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
assert m.ord_char8("Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
assert str(excinfo.value) == toobig_message(0x100)
with pytest.raises(ValueError) as excinfo:
assert m.ord_char8(u"ab")
assert m.ord_char8("ab")
assert str(excinfo.value) == toolong_message
@ -123,18 +124,13 @@ def test_bytes_to_string():
one-way: the only way to return bytes to Python is via the pybind11::bytes class."""
# Issue #816
def to_bytes(s):
b = s if env.PY2 else s.encode("utf8")
assert isinstance(b, bytes)
return b
assert m.strlen(to_bytes("hi")) == 2
assert m.string_length(to_bytes("world")) == 5
assert m.string_length(to_bytes("a\x00b")) == 3
assert m.strlen(to_bytes("a\x00b")) == 1 # C-string limitation
assert m.strlen(b"hi") == 2
assert m.string_length(b"world") == 5
assert m.string_length("a\x00b".encode()) == 3
assert m.strlen("a\x00b".encode()) == 1 # C-string limitation
# passing in a utf8 encoded string should work
assert m.string_length(u"💩".encode("utf8")) == 4
assert m.string_length("💩".encode()) == 4
@pytest.mark.skipif(not hasattr(m, "has_string_view"), reason="no <string_view>")
@ -142,26 +138,26 @@ def test_string_view(capture):
"""Tests support for C++17 string_view arguments and return values"""
assert m.string_view_chars("Hi") == [72, 105]
assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
assert m.string_view16_chars(u"Hi 🎂") == [72, 105, 32, 0xD83C, 0xDF82]
assert m.string_view32_chars(u"Hi 🎂") == [72, 105, 32, 127874]
assert m.string_view16_chars("Hi 🎂") == [72, 105, 32, 0xD83C, 0xDF82]
assert m.string_view32_chars("Hi 🎂") == [72, 105, 32, 127874]
if hasattr(m, "has_u8string"):
assert m.string_view8_chars("Hi") == [72, 105]
assert m.string_view8_chars(u"Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
assert m.string_view8_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
assert m.string_view_return() == u"utf8 secret 🎂"
assert m.string_view16_return() == u"utf16 secret 🎂"
assert m.string_view32_return() == u"utf32 secret 🎂"
assert m.string_view_return() == "utf8 secret 🎂"
assert m.string_view16_return() == "utf16 secret 🎂"
assert m.string_view32_return() == "utf32 secret 🎂"
if hasattr(m, "has_u8string"):
assert m.string_view8_return() == u"utf8 secret 🎂"
assert m.string_view8_return() == "utf8 secret 🎂"
with capture:
m.string_view_print("Hi")
m.string_view_print("utf8 🎂")
m.string_view16_print(u"utf16 🎂")
m.string_view32_print(u"utf32 🎂")
m.string_view16_print("utf16 🎂")
m.string_view32_print("utf32 🎂")
assert (
capture
== u"""
== """
Hi 2
utf8 🎂 9
utf16 🎂 8
@ -171,10 +167,10 @@ def test_string_view(capture):
if hasattr(m, "has_u8string"):
with capture:
m.string_view8_print("Hi")
m.string_view8_print(u"utf8 🎂")
m.string_view8_print("utf8 🎂")
assert (
capture
== u"""
== """
Hi 2
utf8 🎂 9
"""
@ -183,11 +179,11 @@ def test_string_view(capture):
with capture:
m.string_view_print("Hi, ascii")
m.string_view_print("Hi, utf8 🎂")
m.string_view16_print(u"Hi, utf16 🎂")
m.string_view32_print(u"Hi, utf32 🎂")
m.string_view16_print("Hi, utf16 🎂")
m.string_view32_print("Hi, utf32 🎂")
assert (
capture
== u"""
== """
Hi, ascii 9
Hi, utf8 🎂 13
Hi, utf16 🎂 12
@ -197,21 +193,20 @@ def test_string_view(capture):
if hasattr(m, "has_u8string"):
with capture:
m.string_view8_print("Hi, ascii")
m.string_view8_print(u"Hi, utf8 🎂")
m.string_view8_print("Hi, utf8 🎂")
assert (
capture
== u"""
== """
Hi, ascii 9
Hi, utf8 🎂 13
"""
)
assert m.string_view_bytes() == b"abc \x80\x80 def"
assert m.string_view_str() == u"abc ‽ def"
assert m.string_view_from_bytes(u"abc ‽ def".encode("utf-8")) == u"abc ‽ def"
assert m.string_view_str() == "abc ‽ def"
assert m.string_view_from_bytes("abc ‽ def".encode()) == "abc ‽ def"
if hasattr(m, "has_u8string"):
assert m.string_view8_str() == u"abc ‽ def"
if not env.PY2:
assert m.string_view8_str() == "abc ‽ def"
assert m.string_view_memoryview() == "Have some 🎂".encode()
assert m.bytes_from_type_with_both_operator_string_and_string_view() == b"success"
@ -224,18 +219,6 @@ def test_integer_casting():
assert m.i64_str(-1) == "-1"
assert m.i32_str(2000000000) == "2000000000"
assert m.u32_str(2000000000) == "2000000000"
if env.PY2:
assert m.i32_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
assert m.i64_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
assert (
m.i64_str(long(-999999999999)) # noqa: F821 undefined name 'long'
== "-999999999999"
)
assert (
m.u64_str(long(999999999999)) # noqa: F821 undefined name 'long'
== "999999999999"
)
else:
assert m.i64_str(-999999999999) == "-999999999999"
assert m.u64_str(999999999999) == "999999999999"
@ -252,46 +235,38 @@ def test_integer_casting():
m.i32_str(3000000000)
assert "incompatible function arguments" in str(excinfo.value)
if env.PY2:
with pytest.raises(TypeError) as excinfo:
m.u32_str(long(-1)) # noqa: F821 undefined name 'long'
assert "incompatible function arguments" in str(excinfo.value)
with pytest.raises(TypeError) as excinfo:
m.u64_str(long(-1)) # noqa: F821 undefined name 'long'
assert "incompatible function arguments" in str(excinfo.value)
def test_int_convert():
class Int(object):
class Int:
def __int__(self):
return 42
class NotInt(object):
class NotInt:
pass
class Float(object):
class Float:
def __float__(self):
return 41.99999
class Index(object):
class Index:
def __index__(self):
return 42
class IntAndIndex(object):
class IntAndIndex:
def __int__(self):
return 42
def __index__(self):
return 0
class RaisingTypeErrorOnIndex(object):
class RaisingTypeErrorOnIndex:
def __index__(self):
raise TypeError
def __int__(self):
return 42
class RaisingValueErrorOnIndex(object):
class RaisingValueErrorOnIndex:
def __index__(self):
raise ValueError
@ -311,7 +286,7 @@ def test_int_convert():
cant_convert(3.14159)
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
if (3, 8) <= env.PY < (3, 10) and env.CPYTHON:
if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
with env.deprecated_call():
assert convert(Int()) == 42
else:
@ -348,7 +323,7 @@ def test_numpy_int_convert():
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
# https://github.com/pybind/pybind11/issues/3408
if (3, 8) <= env.PY < (3, 10) and env.CPYTHON:
if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
with env.deprecated_call():
assert convert(np.float32(3.14159)) == 3
else:
@ -475,7 +450,7 @@ def test_bool_caster():
require_implicit(None)
assert convert(None) is False
class A(object):
class A:
def __init__(self, x):
self.x = x
@ -485,7 +460,7 @@ def test_bool_caster():
def __bool__(self):
return self.x
class B(object):
class B:
pass
# Arbitrary objects are not accepted
@ -515,17 +490,9 @@ def test_numpy_bool():
def test_int_long():
"""In Python 2, a C++ int should return a Python int rather than long
if possible: longs are not always accepted where ints are used (such
as the argument to sys.exit()). A C++ long long is always a Python
long."""
import sys
must_be_long = type(getattr(sys, "maxint", 1) + 1)
assert isinstance(m.int_cast(), int)
assert isinstance(m.long_cast(), int)
assert isinstance(m.longlong_cast(), must_be_long)
assert isinstance(m.longlong_cast(), int)
def test_void_caster_2():

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import time
from threading import Thread

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import datetime
import pytest

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401
@ -7,7 +6,6 @@ from pybind11_tests import class_ as m
def test_repr():
# In Python 3.3+, repr() accesses __qualname__
assert "pybind11_type" in repr(type(UserType))
assert "UserType" in repr(UserType)
@ -103,8 +101,8 @@ def test_docstrings(doc):
def test_qualname(doc):
"""Tests that a properly qualified name is set in __qualname__ (even in pre-3.3, where we
backport the attribute) and that generated docstrings properly use it and the module name"""
"""Tests that a properly qualified name is set in __qualname__ and that
generated docstrings properly use it and the module name"""
assert m.NestBase.__qualname__ == "NestBase"
assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
@ -130,13 +128,13 @@ def test_qualname(doc):
doc(m.NestBase.Nested.fn)
== """
fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
""" # noqa: E501 line too long
"""
)
assert (
doc(m.NestBase.Nested.fa)
== """
fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
""" # noqa: E501 line too long
"""
)
assert m.NestBase.__module__ == "pybind11_tests.class_"
assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"

View File

@ -1,10 +1,8 @@
# -*- coding: utf-8 -*-
import sys
import test_cmake_build
if str is not bytes: # If not Python2
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
print("{} imports, runs, and adds: 1 + 2 = 3".format(sys.argv[1]))

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
import pytest
import env
from pybind11_tests import const_name as m
@ -25,7 +23,7 @@ from pybind11_tests import const_name as m
),
)
def test_const_name(func, selector, expected):
if isinstance(func, type(u"") if env.PY2 else str):
if isinstance(func, str):
pytest.skip(func)
text = func(selector)
assert text == expected

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
m = pytest.importorskip("pybind11_tests.constants_and_functions")

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import copy_move_policies as m

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import custom_type_casters as m
@ -19,7 +18,7 @@ def test_noconvert_args(msg):
loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
13
loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
""" # noqa: E501 line too long
"""
)
assert (
msg(a.g("this is a", "this is b", 42))
@ -28,7 +27,7 @@ def test_noconvert_args(msg):
loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
42
loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
""" # noqa: E501 line too long
"""
)
assert (
msg(a.g("this is a", "this is b", 42, "this is d"))
@ -76,7 +75,7 @@ def test_noconvert_args(msg):
1. (i: int) -> int
Invoked with: 4.0
""" # noqa: E501 line too long
"""
)
assert m.ints_only(4) == 2

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import gc
import weakref

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from pybind11_tests import docstring_options as m

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import ConstructorStats
@ -201,7 +200,7 @@ def test_negative_stride_from_python(msg):
double_threer(): incompatible function arguments. The following argument types are supported:
1. (arg0: numpy.ndarray[numpy.float32[1, 3], flags.writeable]) -> None
Invoked with: """ # noqa: E501 line too long
Invoked with: """
+ repr(np.array([5.0, 4.0, 3.0], dtype="float32"))
)
@ -213,7 +212,7 @@ def test_negative_stride_from_python(msg):
double_threec(): incompatible function arguments. The following argument types are supported:
1. (arg0: numpy.ndarray[numpy.float32[3, 1], flags.writeable]) -> None
Invoked with: """ # noqa: E501 line too long
Invoked with: """
+ repr(np.array([7.0, 4.0, 1.0], dtype="float32"))
)
@ -724,13 +723,13 @@ def test_sparse_signature(doc):
doc(m.sparse_copy_r)
== """
sparse_copy_r(arg0: scipy.sparse.csr_matrix[numpy.float32]) -> scipy.sparse.csr_matrix[numpy.float32]
""" # noqa: E501 line too long
"""
)
assert (
doc(m.sparse_copy_c)
== """
sparse_copy_c(arg0: scipy.sparse.csc_matrix[numpy.float32]) -> scipy.sparse.csc_matrix[numpy.float32]
""" # noqa: E501 line too long
"""
)

View File

@ -126,7 +126,6 @@ TEST_CASE("Override cache") {
TEST_CASE("Import error handling") {
REQUIRE_NOTHROW(py::module_::import("widget_module"));
REQUIRE_THROWS_WITH(py::module_::import("throw_exception"), "ImportError: C++ Error");
#if PY_VERSION_HEX >= 0x03030000
REQUIRE_THROWS_WITH(py::module_::import("throw_error_already_set"),
Catch::Contains("ImportError: initialization failed"));
@ -142,10 +141,6 @@ TEST_CASE("Import error handling") {
locals);
REQUIRE(locals["is_keyerror"].cast<bool>() == true);
REQUIRE(locals["message"].cast<std::string>() == "'missing'");
#else
REQUIRE_THROWS_WITH(py::module_::import("throw_error_already_set"),
Catch::Contains("ImportError: KeyError"));
#endif
}
TEST_CASE("There can be only one interpreter") {

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import sys
from widget_module import Widget
@ -6,7 +5,7 @@ from widget_module import Widget
class DerivedWidget(Widget):
def __init__(self, message):
super(DerivedWidget, self).__init__(message)
super().__init__(message)
def the_answer(self):
return 42

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import trampoline_module

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
import pytest
import env
from pybind11_tests import enums as m
@ -241,9 +239,6 @@ def test_char_underlying_enum(): # Issue #1331/PR #1334:
assert type(m.ScopedCharEnum.Positive.__int__()) is int
assert int(m.ScopedChar16Enum.Zero) == 0
assert hash(m.ScopedChar32Enum.Positive) == 1
if env.PY2:
assert m.ScopedCharEnum.Positive.__getstate__() == 1 # long
else:
assert type(m.ScopedCharEnum.Positive.__getstate__()) is int
assert m.ScopedWCharEnum(1) == m.ScopedWCharEnum.Positive
with pytest.raises(TypeError):
@ -255,9 +250,6 @@ def test_bool_underlying_enum():
assert type(m.ScopedBoolEnum.TRUE.__int__()) is int
assert int(m.ScopedBoolEnum.FALSE) == 0
assert hash(m.ScopedBoolEnum.TRUE) == 1
if env.PY2:
assert m.ScopedBoolEnum.TRUE.__getstate__() == 1 # long
else:
assert type(m.ScopedBoolEnum.TRUE.__getstate__()) is int
assert m.ScopedBoolEnum(1) == m.ScopedBoolEnum.TRUE
# Enum could construct with a bool

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import os
import pytest
@ -18,7 +17,7 @@ def test_evals(capture):
assert m.test_eval_failure()
@pytest.mark.xfail("env.PYPY and not env.PY2", raises=RuntimeError)
@pytest.mark.xfail("env.PYPY", raises=RuntimeError)
def test_eval_file():
filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py")
assert m.test_eval_file(filename)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
# This file is called from 'test_eval.py'
if "call_test2" in locals():

View File

@ -276,8 +276,6 @@ TEST_SUBMODULE(exceptions, m) {
m.def("throw_should_be_translated_to_key_error", []() { throw shared_exception(); });
#if PY_VERSION_HEX >= 0x03030000
m.def("raise_from", []() {
PyErr_SetString(PyExc_ValueError, "inner");
py::raise_from(PyExc_ValueError, "outer");
@ -301,5 +299,4 @@ TEST_SUBMODULE(exceptions, m) {
std::throw_with_nested(std::runtime_error("Outer Exception"));
}
});
#endif
}

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import sys
import pytest
@ -24,7 +23,6 @@ def test_error_already_set(msg):
assert msg(excinfo.value) == "foo"
@pytest.mark.skipif("env.PY2")
def test_raise_from(msg):
with pytest.raises(ValueError) as excinfo:
m.raise_from()
@ -32,7 +30,6 @@ def test_raise_from(msg):
assert msg(excinfo.value.__cause__) == "inner"
@pytest.mark.skipif("env.PY2")
def test_raise_from_already_set(msg):
with pytest.raises(ValueError) as excinfo:
m.raise_from_already_set()
@ -102,7 +99,7 @@ def ignore_pytest_unraisable_warning(f):
@ignore_pytest_unraisable_warning
def test_python_alreadyset_in_destructor(monkeypatch, capsys):
hooked = False
triggered = [False] # mutable, so Python 2.7 closure can modify it
triggered = False
if hasattr(sys, "unraisablehook"): # Python 3.8+
hooked = True
@ -112,7 +109,8 @@ def test_python_alreadyset_in_destructor(monkeypatch, capsys):
def hook(unraisable_hook_args):
exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
if obj == "already_set demo":
triggered[0] = True
nonlocal triggered
triggered = True
default_hook(unraisable_hook_args)
return
@ -121,11 +119,11 @@ def test_python_alreadyset_in_destructor(monkeypatch, capsys):
assert m.python_alreadyset_in_destructor("already_set demo") is True
if hooked:
assert triggered[0] is True
assert triggered is True
_, captured_stderr = capsys.readouterr()
# Error message is different in Python 2 and 3, check for words that appear in both
assert "ignored" in captured_stderr and "already_set demo" in captured_stderr
assert captured_stderr.startswith("Exception ignored in: 'already_set demo'")
assert captured_stderr.rstrip().endswith("KeyError: 'bar'")
def test_exception_matches():
@ -239,7 +237,6 @@ def test_nested_throws(capture):
assert str(excinfo.value) == "this is a helper-defined translated exception"
@pytest.mark.skipif("env.PY2")
def test_throw_nested_exception():
with pytest.raises(RuntimeError) as excinfo:
m.throw_nested_exception()
@ -249,7 +246,7 @@ def test_throw_nested_exception():
# This can often happen if you wrap a pybind11 class in a Python wrapper
def test_invalid_repr():
class MyRepr(object):
class MyRepr:
def __repr__(self):
raise AttributeError("Example error")

View File

@ -1,9 +1,7 @@
# -*- coding: utf-8 -*-
import re
import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats
from pybind11_tests import factory_constructors as m
from pybind11_tests.factory_constructors import tag
@ -82,7 +80,7 @@ def test_init_factory_signature(msg):
4. m.factory_constructors.TestFactory1(arg0: handle, arg1: int, arg2: handle)
Invoked with: 'invalid', 'constructor', 'arguments'
""" # noqa: E501 line too long
"""
)
assert (
@ -465,12 +463,10 @@ def test_reallocation_g(capture, msg):
)
@pytest.mark.skipif("env.PY2")
def test_invalid_self():
"""Tests invocation of the pybind-registered base class with an invalid `self` argument. You
can only actually do this on Python 3: Python 2 raises an exception itself if you try."""
"""Tests invocation of the pybind-registered base class with an invalid `self` argument."""
class NotPybindDerived(object):
class NotPybindDerived:
pass
# Attempts to initialize with an invalid type passed as `self`:

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import multiprocessing
import threading

View File

@ -1,44 +1,8 @@
# -*- coding: utf-8 -*-
import sys
from contextlib import contextmanager
from contextlib import redirect_stderr, redirect_stdout
from io import StringIO
from pybind11_tests import iostream as m
try:
# Python 3
from io import StringIO
except ImportError:
# Python 2
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
try:
# Python 3.4
from contextlib import redirect_stdout
except ImportError:
@contextmanager
def redirect_stdout(target):
original = sys.stdout
sys.stdout = target
yield
sys.stdout = original
try:
# Python 3.5
from contextlib import redirect_stderr
except ImportError:
@contextmanager
def redirect_stderr(target):
original = sys.stderr
sys.stderr = target
yield
sys.stderr = original
def test_captured(capsys):
msg = "I've been redirected to Python, I hope!"

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401
from pybind11_tests import kwargs_and_defaults as m
@ -82,7 +80,7 @@ def test_mixed_args_and_kwargs(msg):
1. (arg0: int, arg1: float, *args) -> tuple
Invoked with: 1
""" # noqa: E501 line too long
"""
)
with pytest.raises(TypeError) as excinfo:
assert mpa()
@ -93,7 +91,7 @@ def test_mixed_args_and_kwargs(msg):
1. (arg0: int, arg1: float, *args) -> tuple
Invoked with:
""" # noqa: E501 line too long
"""
)
assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == (
@ -127,7 +125,7 @@ def test_mixed_args_and_kwargs(msg):
1. (i: int = 1, j: float = 3.14159, *args, **kwargs) -> tuple
Invoked with: 1; kwargs: i=1
""" # noqa: E501 line too long
"""
)
with pytest.raises(TypeError) as excinfo:
assert mpakd(1, 2, j=1)
@ -138,7 +136,7 @@ def test_mixed_args_and_kwargs(msg):
1. (i: int = 1, j: float = 3.14159, *args, **kwargs) -> tuple
Invoked with: 1, 2; kwargs: j=1
""" # noqa: E501 line too long
"""
)
# Arguments after a py::args are automatically keyword-only (pybind 2.9+)
@ -343,7 +341,6 @@ def test_signatures():
)
@pytest.mark.xfail("env.PYPY and env.PY2", reason="PyPy2 doesn't double count")
def test_args_refcount():
"""Issue/PR #1216 - py::args elements get double-inc_ref()ed when combined with regular
arguments"""

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401
@ -200,7 +199,7 @@ def test_stl_caster_vs_stl_bind(msg):
1. (arg0: pybind11_cross_module_tests.VectorInt) -> int
Invoked with: [1, 2, 3]
""" # noqa: E501 line too long
"""
)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401
@ -494,26 +493,17 @@ def test_overload_ordering():
assert m.overload_order("string") == 1
assert m.overload_order(0) == 4
# Different for Python 2 vs. 3
uni_name = type(u"").__name__
assert "1. overload_order(arg0: int) -> int" in m.overload_order.__doc__
assert (
"2. overload_order(arg0: {}) -> int".format(uni_name)
in m.overload_order.__doc__
)
assert (
"3. overload_order(arg0: {}) -> int".format(uni_name)
in m.overload_order.__doc__
)
assert "2. overload_order(arg0: str) -> int" in m.overload_order.__doc__
assert "3. overload_order(arg0: str) -> int" in m.overload_order.__doc__
assert "4. overload_order(arg0: int) -> int" in m.overload_order.__doc__
with pytest.raises(TypeError) as err:
m.overload_order(1.1)
assert "1. (arg0: int) -> int" in str(err.value)
assert "2. (arg0: {}) -> int".format(uni_name) in str(err.value)
assert "3. (arg0: {}) -> int".format(uni_name) in str(err.value)
assert "2. (arg0: str) -> int" in str(err.value)
assert "3. (arg0: str) -> int" in str(err.value)
assert "4. (arg0: int) -> int" in str(err.value)

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from pybind11_tests import ConstructorStats
from pybind11_tests import modules as m
from pybind11_tests.modules import subsubmodule as ms

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401
@ -13,8 +12,7 @@ def test_multiple_inheritance_cpp():
assert mt.bar() == 4
@pytest.mark.skipif("env.PYPY and env.PY2")
@pytest.mark.xfail("env.PYPY and not env.PY2")
@pytest.mark.xfail("env.PYPY")
def test_multiple_inheritance_mix1():
class Base1:
def __init__(self, i):
@ -53,15 +51,14 @@ def test_multiple_inheritance_mix2():
assert mt.bar() == 4
@pytest.mark.skipif("env.PYPY and env.PY2")
@pytest.mark.xfail("env.PYPY and not env.PY2")
@pytest.mark.xfail("env.PYPY")
def test_multiple_inheritance_python():
class MI1(m.Base1, m.Base2):
def __init__(self, i, j):
m.Base1.__init__(self, i)
m.Base2.__init__(self, j)
class B1(object):
class B1:
def v(self):
return 1
@ -96,7 +93,7 @@ def test_multiple_inheritance_python():
def v(self):
return 2
class B3(object):
class B3:
def v(self):
return 3

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import re
import pytest

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import numpy_vectorize as m

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import ConstructorStats, UserType
@ -40,7 +39,7 @@ def test_pointers(msg):
1. (arg0: capsule) -> int
Invoked with: [1, 2, 3]
""" # noqa: E501 line too long
"""
)
assert m.return_null_str() is None

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
import pytest
import env
from pybind11_tests import ConstructorStats
from pybind11_tests import operators as m
@ -151,5 +149,4 @@ def test_overriding_eq_reset_hash():
def test_return_set_of_unhashable():
with pytest.raises(TypeError) as excinfo:
m.get_unhashable_HashMe_set()
if not env.PY2:
assert str(excinfo.value.__cause__).startswith("unhashable type:")

View File

@ -1,14 +1,10 @@
# -*- coding: utf-8 -*-
import pickle
import pytest
import env
from pybind11_tests import pickling as m
try:
import cPickle as pickle # Use cPickle on Python 2.7
except ImportError:
import pickle
@pytest.mark.parametrize("cls_name", ["Pickleable", "PickleableNew"])
def test_roundtrip(cls_name):

View File

@ -87,7 +87,6 @@ TEST_SUBMODULE(pytypes, m) {
m.def("tuple_size_t", []() { return py::tuple{(py::size_t) 0}; });
m.def("get_tuple", []() { return py::make_tuple(42, py::none(), "spam"); });
#if PY_VERSION_HEX >= 0x03030000
// test_simple_namespace
m.def("get_simple_namespace", []() {
auto ns = py::module_::import("types").attr("SimpleNamespace")(
@ -96,7 +95,6 @@ TEST_SUBMODULE(pytypes, m) {
py::setattr(ns, "right", py::int_(2));
return ns;
});
#endif
// test_str
m.def("str_from_char_ssize_t", []() { return py::str{"red", (py::ssize_t) 3}; });
@ -423,12 +421,10 @@ TEST_SUBMODULE(pytypes, m) {
return py::memoryview::from_buffer(static_cast<void *>(nullptr), 1, "B", {}, {});
});
#if PY_MAJOR_VERSION >= 3
m.def("test_memoryview_from_memory", []() {
const char *buf = "\xff\xe1\xab\x37";
return py::memoryview::from_memory(buf, static_cast<py::ssize_t>(strlen(buf)));
});
#endif
// test_builtin_functions
m.def("get_len", [](py::handle h) { return py::len(h); });

View File

@ -1,11 +1,8 @@
# -*- coding: utf-8 -*-
from __future__ import division
import sys
import pytest
import env
import env # noqa: F401
from pybind11_tests import debug_enabled
from pybind11_tests import pytypes as m
@ -123,7 +120,6 @@ def test_tuple():
assert m.get_tuple() == (42, None, "spam")
@pytest.mark.skipif("env.PY2")
def test_simple_namespace():
ns = m.get_simple_namespace()
assert ns.attr == 42
@ -140,7 +136,7 @@ def test_str(doc):
assert doc(m.str_from_bytes) == "str_from_bytes() -> str"
class A(object):
class A:
def __str__(self):
return "this is a str"
@ -158,22 +154,12 @@ def test_str(doc):
malformed_utf8 = b"\x80"
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE"):
assert m.str_from_object(malformed_utf8) is malformed_utf8
elif env.PY2:
with pytest.raises(UnicodeDecodeError):
m.str_from_object(malformed_utf8)
else:
assert m.str_from_object(malformed_utf8) == "b'\\x80'"
if env.PY2:
with pytest.raises(UnicodeDecodeError):
m.str_from_handle(malformed_utf8)
else:
assert m.str_from_handle(malformed_utf8) == "b'\\x80'"
assert m.str_from_string_from_str("this is a str") == "this is a str"
ucs_surrogates_str = u"\udcc3"
if env.PY2:
assert u"\udcc3" == m.str_from_string_from_str(ucs_surrogates_str)
else:
ucs_surrogates_str = "\udcc3"
with pytest.raises(UnicodeEncodeError):
m.str_from_string_from_str(ucs_surrogates_str)
@ -184,9 +170,7 @@ def test_bytes(doc):
assert m.bytes_from_string().decode() == "foo"
assert m.bytes_from_str().decode() == "bar"
assert doc(m.bytes_from_str) == "bytes_from_str() -> {}".format(
"str" if env.PY2 else "bytes"
)
assert doc(m.bytes_from_str) == "bytes_from_str() -> bytes"
def test_bytearray(doc):
@ -278,11 +262,6 @@ def test_constructors():
"""C++ default and converting constructors are equivalent to type calls in Python"""
types = [bytes, bytearray, str, bool, int, float, tuple, list, dict, set]
expected = {t.__name__: t() for t in types}
if env.PY2:
# Note that bytes.__name__ == 'str' in Python 2.
# pybind11::str is unicode even under Python 2.
expected["bytes"] = bytes()
expected["str"] = unicode() # noqa: F821
assert m.default_constructors() == expected
data = {
@ -300,11 +279,6 @@ def test_constructors():
}
inputs = {k.__name__: v for k, v in data.items()}
expected = {k.__name__: k(v) for k, v in data.items()}
if env.PY2: # Similar to the above. See comments above.
inputs["bytes"] = b"41"
inputs["str"] = 42
expected["bytes"] = b"41"
expected["str"] = u"42"
assert m.converting_constructors(inputs) == expected
assert m.cast_functions(inputs) == expected
@ -340,42 +314,35 @@ def test_non_converting_constructors():
def test_pybind11_str_raw_str():
# specifically to exercise pybind11::str::raw_str
cvt = m.convert_to_pybind11_str
assert cvt(u"Str") == u"Str"
assert cvt(b"Bytes") == u"Bytes" if env.PY2 else "b'Bytes'"
assert cvt(None) == u"None"
assert cvt(False) == u"False"
assert cvt(True) == u"True"
assert cvt(42) == u"42"
assert cvt(2 ** 65) == u"36893488147419103232"
assert cvt(-1.50) == u"-1.5"
assert cvt(()) == u"()"
assert cvt((18,)) == u"(18,)"
assert cvt([]) == u"[]"
assert cvt([28]) == u"[28]"
assert cvt({}) == u"{}"
assert cvt({3: 4}) == u"{3: 4}"
assert cvt(set()) == u"set([])" if env.PY2 else "set()"
assert cvt({3, 3}) == u"set([3])" if env.PY2 else "{3}"
assert cvt("Str") == "Str"
assert cvt(b"Bytes") == "b'Bytes'"
assert cvt(None) == "None"
assert cvt(False) == "False"
assert cvt(True) == "True"
assert cvt(42) == "42"
assert cvt(2**65) == "36893488147419103232"
assert cvt(-1.50) == "-1.5"
assert cvt(()) == "()"
assert cvt((18,)) == "(18,)"
assert cvt([]) == "[]"
assert cvt([28]) == "[28]"
assert cvt({}) == "{}"
assert cvt({3: 4}) == "{3: 4}"
assert cvt(set()) == "set()"
assert cvt({3, 3}) == "{3}"
valid_orig = u"DZ"
valid_orig = "DZ"
valid_utf8 = valid_orig.encode("utf-8")
valid_cvt = cvt(valid_utf8)
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE"):
assert valid_cvt is valid_utf8
else:
assert type(valid_cvt) is unicode if env.PY2 else str # noqa: F821
if env.PY2:
assert valid_cvt == valid_orig
else:
assert type(valid_cvt) is str
assert valid_cvt == "b'\\xc7\\xb1'"
malformed_utf8 = b"\x80"
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE"):
assert cvt(malformed_utf8) is malformed_utf8
else:
if env.PY2:
with pytest.raises(UnicodeDecodeError):
cvt(malformed_utf8)
else:
malformed_cvt = cvt(malformed_utf8)
assert type(malformed_cvt) is str
@ -428,14 +395,14 @@ def test_print(capture):
def test_hash():
class Hashable(object):
class Hashable:
def __init__(self, value):
self.value = value
def __hash__(self):
return self.value
class Unhashable(object):
class Unhashable:
__hash__ = None
assert m.hash_function(Hashable(42)) == 42
@ -493,12 +460,7 @@ def test_memoryview(method, args, fmt, expected_view):
view = method(*args)
assert isinstance(view, memoryview)
assert view.format == fmt
if isinstance(expected_view, bytes) or not env.PY2:
view_as_list = list(view)
else:
# Using max to pick non-zero byte (big-endian vs little-endian).
view_as_list = [max(ord(c) for c in s) for s in view]
assert view_as_list == list(expected_view)
assert list(view) == list(expected_view)
@pytest.mark.xfail("env.PYPY", reason="getrefcount is not available")
@ -522,11 +484,6 @@ def test_memoryview_from_buffer_empty_shape():
view = m.test_memoryview_from_buffer_empty_shape()
assert isinstance(view, memoryview)
assert view.format == "B"
if env.PY2:
# Python 2 behavior is weird, but Python 3 (the future) is fine.
# PyPy3 has <memoryview, while CPython 2 has <memory
assert bytes(view).startswith(b"<memory")
else:
assert bytes(view) == b""
@ -536,14 +493,10 @@ def test_test_memoryview_from_buffer_invalid_strides():
def test_test_memoryview_from_buffer_nullptr():
if env.PY2:
m.test_memoryview_from_buffer_nullptr()
else:
with pytest.raises(ValueError):
m.test_memoryview_from_buffer_nullptr()
@pytest.mark.skipif("env.PY2")
def test_memoryview_from_memory():
view = m.test_memoryview_from_memory()
assert isinstance(view, memoryview)
@ -563,9 +516,9 @@ def test_builtin_functions():
def test_isinstance_string_types():
assert m.isinstance_pybind11_bytes(b"")
assert not m.isinstance_pybind11_bytes(u"")
assert not m.isinstance_pybind11_bytes("")
assert m.isinstance_pybind11_str(u"")
assert m.isinstance_pybind11_str("")
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE"):
assert m.isinstance_pybind11_str(b"")
else:
@ -575,24 +528,21 @@ def test_isinstance_string_types():
def test_pass_bytes_or_unicode_to_string_types():
assert m.pass_to_pybind11_bytes(b"Bytes") == 5
with pytest.raises(TypeError):
m.pass_to_pybind11_bytes(u"Str")
m.pass_to_pybind11_bytes("Str")
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE") or env.PY2:
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE"):
assert m.pass_to_pybind11_str(b"Bytes") == 5
else:
with pytest.raises(TypeError):
m.pass_to_pybind11_str(b"Bytes")
assert m.pass_to_pybind11_str(u"Str") == 3
assert m.pass_to_pybind11_str("Str") == 3
assert m.pass_to_std_string(b"Bytes") == 5
assert m.pass_to_std_string(u"Str") == 3
assert m.pass_to_std_string("Str") == 3
malformed_utf8 = b"\x80"
if hasattr(m, "PYBIND11_STR_LEGACY_PERMISSIVE"):
assert m.pass_to_pybind11_str(malformed_utf8) == 1
elif env.PY2:
with pytest.raises(UnicodeDecodeError):
m.pass_to_pybind11_str(malformed_utf8)
else:
with pytest.raises(TypeError):
m.pass_to_pybind11_str(malformed_utf8)
@ -609,12 +559,14 @@ def test_weakref(create_weakref, create_weakref_with_callback):
from weakref import getweakrefcount
# Apparently, you cannot weakly reference an object()
class WeaklyReferenced(object):
class WeaklyReferenced:
pass
callback_called = False
def callback(wr):
# No `nonlocal` in Python 2
callback.called = True
nonlocal callback_called
callback_called = True
obj = WeaklyReferenced()
assert getweakrefcount(obj) == 0
@ -623,13 +575,12 @@ def test_weakref(create_weakref, create_weakref_with_callback):
obj = WeaklyReferenced()
assert getweakrefcount(obj) == 0
callback.called = False
wr = create_weakref_with_callback(obj, callback) # noqa: F841
assert getweakrefcount(obj) == 1
assert not callback.called
assert not callback_called
del obj
pytest.gc_collect()
assert callback.called
assert callback_called
def test_cpp_iterators():

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import ConstructorStats

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
m = pytest.importorskip("pybind11_tests.smart_ptr")

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import ConstructorStats, UserType
@ -283,7 +282,7 @@ def test_stl_pass_by_pointer(msg):
1. (v: List[int] = None) -> List[int]
Invoked with:
""" # noqa: E501 line too long
"""
)
with pytest.raises(TypeError) as excinfo:
@ -295,7 +294,7 @@ def test_stl_pass_by_pointer(msg):
1. (v: List[int] = None) -> List[int]
Invoked with: None
""" # noqa: E501 line too long
"""
)
assert m.stl_pass_by_pointer([1, 2, 3]) == [1, 2, 3]

View File

@ -1,7 +1,5 @@
# -*- coding: utf-8 -*-
import pytest
import env
from pybind11_tests import stl_binders as m
@ -74,15 +72,10 @@ def test_vector_buffer():
assert v[1] == 2
v[2] = 5
mv = memoryview(v) # We expose the buffer interface
if not env.PY2:
assert mv[2] == 5
mv[2] = 6
else:
assert mv[2] == "\x05"
mv[2] = "\x06"
assert v[2] == 6
if not env.PY2:
mv = memoryview(b)
v = m.VectorUChar(mv[::2])
assert v[1] == 3

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from pybind11_tests import tagbased_polymorphic as m

View File

@ -1,5 +1,3 @@
# -*- coding: utf-8 -*-
import threading
from pybind11_tests import thread as m
@ -7,7 +5,7 @@ from pybind11_tests import thread as m
class Thread(threading.Thread):
def __init__(self, fn):
super(Thread, self).__init__()
super().__init__()
self.fn = fn
self.e = None
@ -19,7 +17,7 @@ class Thread(threading.Thread):
self.e = e
def join(self):
super(Thread, self).join()
super().join()
if self.e:
raise self.e

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from pybind11_tests import union_ as m

View File

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
import pytest
import env # noqa: F401
@ -10,12 +9,12 @@ from pybind11_tests import ConstructorStats # noqa: E402
def test_override(capture, msg):
class ExtendedExampleVirt(m.ExampleVirt):
def __init__(self, state):
super(ExtendedExampleVirt, self).__init__(state + 1)
super().__init__(state + 1)
self.data = "Hello world"
def run(self, value):
print("ExtendedExampleVirt::run(%i), calling parent.." % value)
return super(ExtendedExampleVirt, self).run(value + 1)
return super().run(value + 1)
def run_bool(self):
print("ExtendedExampleVirt::run_bool()")
@ -29,7 +28,7 @@ def test_override(capture, msg):
class ExtendedExampleVirt2(ExtendedExampleVirt):
def __init__(self, state):
super(ExtendedExampleVirt2, self).__init__(state + 1)
super().__init__(state + 1)
def get_string2(self):
return "override2"
@ -41,7 +40,7 @@ def test_override(capture, msg):
capture
== """
Original implementation of ExampleVirt::run(state=10, value=20, str1=default1, str2=default2)
""" # noqa: E501 line too long
"""
)
with pytest.raises(RuntimeError) as excinfo:
@ -59,7 +58,7 @@ def test_override(capture, msg):
== """
ExtendedExampleVirt::run(20), calling parent..
Original implementation of ExampleVirt::run(state=11, value=21, str1=override1, str2=default2)
""" # noqa: E501 line too long
"""
)
with capture:
assert m.runExampleVirtBool(ex12p) is False
@ -76,7 +75,7 @@ def test_override(capture, msg):
== """
ExtendedExampleVirt::run(50), calling parent..
Original implementation of ExampleVirt::run(state=17, value=51, str1=override1, str2=override2)
""" # noqa: E501 line too long
"""
)
cstats = ConstructorStats.get(m.ExampleVirt)
@ -97,7 +96,7 @@ def test_alias_delay_initialization1(capture):
class B(m.A):
def __init__(self):
super(B, self).__init__()
super().__init__()
def f(self):
print("In python f()")
@ -137,7 +136,7 @@ def test_alias_delay_initialization2(capture):
class B2(m.A2):
def __init__(self):
super(B2, self).__init__()
super().__init__()
def f(self):
print("In python B2.f()")
@ -245,7 +244,7 @@ def test_dispatch_issue(msg):
class PyClass2(m.DispatchIssue):
def dispatch(self):
with pytest.raises(RuntimeError) as excinfo:
super(PyClass2, self).dispatch()
super().dispatch()
assert (
msg(excinfo.value)
== 'Tried to call pure virtual function "Base::dispatch"'
@ -262,7 +261,7 @@ def test_recursive_dispatch_issue(msg):
class Data(m.Data):
def __init__(self, value):
super(Data, self).__init__()
super().__init__()
self.value = value
class Adder(m.Adder):

View File

@ -92,7 +92,7 @@ endif()
# Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION)
set(PythonLibsNew_FIND_VERSION "")
set(PythonLibsNew_FIND_VERSION "3.5")
endif()
find_package(PythonInterp ${PythonLibsNew_FIND_VERSION} ${_pythonlibs_required}

View File

@ -1,6 +1,3 @@
# -*- coding: utf-8 -*-
from __future__ import division, print_function
import os
import sys

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import re

View File

@ -8,7 +8,6 @@ Adds the following targets::
pybind11::lto - Link time optimizations (manual selection)
pybind11::thin_lto - Link time optimizations (manual selection)
pybind11::python_link_helper - Adds link to Python libraries
pybind11::python2_no_register - Avoid warning/error with Python 2 + C++14/7
pybind11::windows_extras - MSVC bigobj and mp for building multithreaded
pybind11::opt_size - avoid optimizations that increase code size
@ -66,31 +65,6 @@ set_property(
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::pybind11)
# ----------------------- no register ----------------------
# Workaround for Python 2.7 and C++17 (C++14 as a warning) incompatibility
# This adds the flags -Wno-register and -Wno-deprecated-register if the compiler
# is Clang 3.9+ or AppleClang and the compile language is CXX, or /wd5033 for MSVC (all languages,
# since MSVC didn't recognize COMPILE_LANGUAGE until CMake 3.11+).
add_library(pybind11::python2_no_register INTERFACE IMPORTED ${optional_global})
set(clang_4plus
"$<AND:$<CXX_COMPILER_ID:Clang>,$<NOT:$<VERSION_LESS:$<CXX_COMPILER_VERSION>,3.9>>>")
set(no_register "$<OR:${clang_4plus},$<CXX_COMPILER_ID:AppleClang>>")
if(MSVC AND CMAKE_VERSION VERSION_LESS 3.11)
set(cxx_no_register "${no_register}")
else()
set(cxx_no_register "$<AND:$<COMPILE_LANGUAGE:CXX>,${no_register}>")
endif()
set(msvc "$<CXX_COMPILER_ID:MSVC>")
set_property(
TARGET pybind11::python2_no_register
PROPERTY INTERFACE_COMPILE_OPTIONS
"$<${cxx_no_register}:-Wno-register;-Wno-deprecated-register>" "$<${msvc}:/wd5033>")
# --------------------------- link helper ---------------------------
add_library(pybind11::python_link_helper IMPORTED INTERFACE ${optional_global})

View File

@ -51,8 +51,6 @@ complex applications, and they are available in all modes:
Python headers too.
``pybind11::python_link_helper``
Just the "linking" part of ``pybind11:module``, for CMake < 3.15.
``pybind11::python2_no_register``
Quiets the warning/error when mixing C++14+ and Python 2, also included in ``pybind11::module``.
``pybind11::thin_lto``
An alternative to ``INTERPROCEDURAL_OPTIMIZATION``.
``pybind11::lto``

View File

@ -22,9 +22,7 @@ else()
set(_pybind11_quiet "")
endif()
if(NOT Python_FOUND
AND NOT Python3_FOUND
AND NOT Python2_FOUND)
if(NOT Python_FOUND AND NOT Python3_FOUND)
if(NOT DEFINED Python_FIND_IMPLEMENTATIONS)
set(Python_FIND_IMPLEMENTATIONS CPython PyPy)
endif()
@ -34,7 +32,7 @@ if(NOT Python_FOUND
set(Python_ROOT_DIR "$ENV{pythonLocation}")
endif()
find_package(Python REQUIRED COMPONENTS Interpreter Development ${_pybind11_quiet})
find_package(Python 3.5 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.
@ -51,19 +49,10 @@ if(Python_FOUND)
set(_Python
Python
CACHE INTERNAL "" FORCE)
elseif(Python3_FOUND AND NOT Python2_FOUND)
elseif(Python3_FOUND)
set(_Python
Python3
CACHE INTERNAL "" FORCE)
elseif(Python2_FOUND AND NOT Python3_FOUND)
set(_Python
Python2
CACHE INTERNAL "" FORCE)
else()
message(AUTHOR_WARNING "Python2 and Python3 both present, pybind11 in "
"PYBIND11_NOPYTHON mode (manually activate to silence warning)")
set(_pybind11_nopython ON)
return()
endif()
if(PYBIND11_MASTER_PROJECT)
@ -137,7 +126,7 @@ if(PYTHON_IS_DEBUG)
PROPERTY INTERFACE_COMPILE_DEFINITIONS Py_DEBUG)
endif()
# Check on every access - since Python2 and Python3 could have been used - do nothing in that case.
# Check on every access - since Python can change - do nothing in that case.
if(DEFINED ${_Python}_INCLUDE_DIRS)
# Only add Python for build - must be added during the import for config
@ -159,13 +148,6 @@ if(DEFINED ${_Python}_INCLUDE_DIRS)
CACHE INTERNAL "Directories where pybind11 and possibly Python headers are located")
endif()
if(DEFINED ${_Python}_VERSION AND ${_Python}_VERSION VERSION_LESS 3)
set_property(
TARGET pybind11::pybind11
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
endif()
# In CMake 3.18+, you can find these separately, so include an if
if(TARGET ${_Python}::Python)
set_property(
@ -205,8 +187,6 @@ function(pybind11_add_module target_name)
python_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
elseif("${_Python}" STREQUAL "Python3")
python3_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
elseif("${_Python}" STREQUAL "Python2")
python2_add_library(${target_name} ${lib_type} ${ARG_UNPARSED_ARGUMENTS})
else()
message(FATAL_ERROR "Cannot detect FindPython version: ${_Python}")
endif()
@ -223,10 +203,6 @@ function(pybind11_add_module target_name)
target_link_libraries(${target_name} PRIVATE pybind11::windows_extras)
endif()
if(DEFINED ${_Python}_VERSION AND ${_Python}_VERSION VERSION_LESS 3)
target_link_libraries(${target_name} PRIVATE pybind11::python2_no_register)
endif()
# -fvisibility=hidden is required to allow multiple modules compiled against
# different pybind versions to work properly, and for some features (e.g.
# py::module_local). We force it on everything inside the `pybind11`

View File

@ -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.4"
"3.11;3.10;3.9;3.8;3.7;3.6;3.5"
CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
@ -122,13 +122,6 @@ set_property(
INTERFACE_LINK_LIBRARIES pybind11::python_link_helper
"$<$<OR:$<PLATFORM_ID:Windows>,$<PLATFORM_ID:Cygwin>>:$<BUILD_INTERFACE:${PYTHON_LIBRARIES}>>")
if(PYTHON_VERSION VERSION_LESS 3)
set_property(
TARGET pybind11::pybind11
APPEND
PROPERTY INTERFACE_LINK_LIBRARIES pybind11::python2_no_register)
endif()
set_property(
TARGET pybind11::embed
APPEND

Some files were not shown because too many files have changed in this diff Show More