Unverified Commit 6493f496 authored by Ralf W. Grosse-Kunstleve's avatar Ralf W. Grosse-Kunstleve Committed by GitHub
Browse files

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: default avatarHenry Schreiner <henryschreineriii@gmail.com>
Co-authored-by: default avatarAaron Gokaslan <skylion.aaron@gmail.com>
parent 46dcd9bc
...@@ -11,8 +11,6 @@ environment: ...@@ -11,8 +11,6 @@ environment:
matrix: matrix:
- PYTHON: 36 - PYTHON: 36
CONFIG: Debug CONFIG: Debug
- PYTHON: 27
CONFIG: Debug
install: install:
- ps: | - ps: |
$env:CMAKE_GENERATOR = "Visual Studio 14 2015" $env:CMAKE_GENERATOR = "Visual Studio 14 2015"
......
...@@ -25,7 +25,6 @@ jobs: ...@@ -25,7 +25,6 @@ jobs:
matrix: matrix:
runs-on: [ubuntu-latest, windows-2022, macos-latest] runs-on: [ubuntu-latest, windows-2022, macos-latest]
python: python:
- '2.7'
- '3.5' - '3.5'
- '3.6' - '3.6'
- '3.9' - '3.9'
...@@ -49,13 +48,9 @@ jobs: ...@@ -49,13 +48,9 @@ jobs:
python: '3.6' python: '3.6'
args: > args: >
-DPYBIND11_FINDPYTHON=ON -DPYBIND11_FINDPYTHON=ON
- runs-on: macos-latest
python: 'pypy-2.7'
# Inject a couple Windows 2019 runs # Inject a couple Windows 2019 runs
- runs-on: windows-2019 - runs-on: windows-2019
python: '3.9' python: '3.9'
- runs-on: windows-2019
python: '2.7'
name: "🐍 ${{ matrix.python }} ${{ matrix.runs-on }} x64 ${{ matrix.args }}" name: "🐍 ${{ matrix.python }} ${{ matrix.runs-on }} x64 ${{ matrix.args }}"
runs-on: ${{ matrix.runs-on }} runs-on: ${{ matrix.runs-on }}
...@@ -168,22 +163,6 @@ jobs: ...@@ -168,22 +163,6 @@ jobs:
- name: Interface test - name: Interface test
run: cmake --build build2 --target test_cmake_build 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 # This makes sure the setup_helpers module can build packages using
# setuptools # setuptools
- name: Setuptools helpers test - name: Setuptools helpers test
...@@ -784,7 +763,6 @@ jobs: ...@@ -784,7 +763,6 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
python: python:
- 2.7
- 3.6 - 3.6
- 3.7 - 3.7
# todo: check/cpptest does not support 3.8+ yet # todo: check/cpptest does not support 3.8+ yet
...@@ -832,17 +810,12 @@ jobs: ...@@ -832,17 +810,12 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
python: python:
- 2.7
- 3.5 - 3.5
- 3.7 - 3.7
std: std:
- 14 - 14
include: include:
- python: 2.7
std: 17
args: >
-DCMAKE_CXX_FLAGS="/permissive- /EHsc /GR"
- python: 3.7 - python: 3.7
std: 17 std: 17
args: > args: >
......
...@@ -17,19 +17,19 @@ env: ...@@ -17,19 +17,19 @@ env:
jobs: jobs:
# This builds the sdists and wheels and makes sure the files are exactly as # 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. # challenging matrix element.
test-packaging: test-packaging:
name: 🐍 2.7 • 📦 tests • windows-latest name: 🐍 3.6 • 📦 tests • windows-latest
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Setup 🐍 2.7 - name: Setup 🐍 3.6
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: 2.7 python-version: 3.6
- name: Prepare env - name: Prepare env
run: | run: |
......
...@@ -29,14 +29,15 @@ repos: ...@@ -29,14 +29,15 @@ repos:
- id: mixed-line-ending - id: mixed-line-ending
- id: requirements-txt-fixer - id: requirements-txt-fixer
- id: trailing-whitespace - id: trailing-whitespace
- id: fix-encoding-pragma
exclude: ^noxfile.py$
# Upgrade old Python syntax
- repo: https://github.com/asottile/pyupgrade - repo: https://github.com/asottile/pyupgrade
rev: v2.31.0 rev: v2.31.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py3-plus]
# Nicely sort includes
- repo: https://github.com/PyCQA/isort - repo: https://github.com/PyCQA/isort
rev: 5.10.1 rev: 5.10.1
hooks: hooks:
...@@ -44,20 +45,21 @@ repos: ...@@ -44,20 +45,21 @@ repos:
# Black, the code formatter, natively supports pre-commit # Black, the code formatter, natively supports pre-commit
- repo: https://github.com/psf/black - repo: https://github.com/psf/black
rev: 21.12b0 # Keep in sync with blacken-docs rev: 22.1.0 # Keep in sync with blacken-docs
hooks: hooks:
- id: black - id: black
# Also code format the docs
- repo: https://github.com/asottile/blacken-docs - repo: https://github.com/asottile/blacken-docs
rev: v1.12.0 rev: v1.12.1
hooks: hooks:
- id: blacken-docs - id: blacken-docs
additional_dependencies: 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 # Changes tabs to spaces
- repo: https://github.com/Lucas-C/pre-commit-hooks - repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.1.10 rev: v1.1.11
hooks: hooks:
- id: remove-tabs - id: remove-tabs
...@@ -67,12 +69,15 @@ repos: ...@@ -67,12 +69,15 @@ repos:
hooks: hooks:
- id: pycln - id: pycln
# Checking for common mistakes
- repo: https://github.com/pre-commit/pygrep-hooks - repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.9.0 rev: v1.9.0
hooks: hooks:
- id: python-check-blanket-noqa - id: python-check-blanket-noqa
- id: python-check-blanket-type-ignore - id: python-check-blanket-type-ignore
- id: python-no-log-warn - id: python-no-log-warn
# Python 3.6
# - id: python-use-type-annotations
- id: rst-backticks - id: rst-backticks
- id: rst-directive-colons - id: rst-directive-colons
- id: rst-inline-touching-normal - id: rst-inline-touching-normal
...@@ -87,6 +92,7 @@ repos: ...@@ -87,6 +92,7 @@ repos:
- pep8-naming - pep8-naming
exclude: ^(docs/.*|tools/.*)$ exclude: ^(docs/.*|tools/.*)$
# Automatically remove noqa that are not used
- repo: https://github.com/asottile/yesqa - repo: https://github.com/asottile/yesqa
rev: v1.3.0 rev: v1.3.0
hooks: hooks:
...@@ -107,9 +113,9 @@ repos: ...@@ -107,9 +113,9 @@ repos:
rev: v0.931 rev: v0.931
hooks: hooks:
- id: mypy - id: mypy
# Running per-file misbehaves a bit, so just run on all files, it's fast args: [--show-error-codes]
pass_filenames: false exclude: ^(tests|docs)/
additional_dependencies: [typed_ast] additional_dependencies: [nox, rich]
# Checks the manifest for missing files (native support) # Checks the manifest for missing files (native support)
- repo: https://github.com/mgedmin/check-manifest - repo: https://github.com/mgedmin/check-manifest
...@@ -120,6 +126,7 @@ repos: ...@@ -120,6 +126,7 @@ repos:
stages: [manual] stages: [manual]
additional_dependencies: [cmake, ninja] additional_dependencies: [cmake, ninja]
# Check for spelling
- repo: https://github.com/codespell-project/codespell - repo: https://github.com/codespell-project/codespell
rev: v2.1.0 rev: v2.1.0
hooks: hooks:
...@@ -127,20 +134,22 @@ repos: ...@@ -127,20 +134,22 @@ repos:
exclude: ".supp$" exclude: ".supp$"
args: ["-L", "nd,ot,thist"] args: ["-L", "nd,ot,thist"]
# Check for common shell mistakes
- repo: https://github.com/shellcheck-py/shellcheck-py - repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.8.0.3 rev: v0.8.0.4
hooks: hooks:
- id: shellcheck - id: shellcheck
# The original pybind11 checks for a few C++ style items # Disallow some common capitalization mistakes
- repo: local - repo: local
hooks: hooks:
- id: disallow-caps - id: disallow-caps
name: Disallow improper capitalization name: Disallow improper capitalization
language: pygrep language: pygrep
entry: PyBind|Numpy|Cmake|CCache|PyTest 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 - repo: https://github.com/pre-commit/mirrors-clang-format
rev: "v13.0.0" rev: "v13.0.0"
hooks: hooks:
......
recursive-include pybind11/include/pybind11 *.h recursive-include pybind11/include/pybind11 *.h
recursive-include pybind11 *.py recursive-include pybind11 *.py
recursive-include pybind11 py.typed recursive-include pybind11 py.typed
recursive-include pybind11 *.pyi
include pybind11/share/cmake/pybind11/*.cmake include pybind11/share/cmake/pybind11/*.cmake
include LICENSE README.rst pyproject.toml setup.py setup.cfg include LICENSE README.rst pyproject.toml setup.py setup.cfg
...@@ -34,7 +34,7 @@ dependency. ...@@ -34,7 +34,7 @@ dependency.
Think of this library as a tiny self-contained version of Boost.Python Think of this library as a tiny self-contained version of Boost.Python
with everything stripped away that isn’t relevant for binding with everything stripped away that isn’t relevant for binding
generation. Without comments, the core header files only require ~4K generation. Without comments, the core header files only require ~4K
lines of code and depend on Python (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 standard library. This compact implementation was possible thanks to
some of the new C++11 language features (specifically: tuples, lambda some of the new C++11 language features (specifically: tuples, lambda
functions and variadic templates). Since its creation, this library has functions and variadic templates). Since its creation, this library has
...@@ -78,8 +78,8 @@ Goodies ...@@ -78,8 +78,8 @@ Goodies
In addition to the core functionality, pybind11 provides some extra In addition to the core functionality, pybind11 provides some extra
goodies: goodies:
- Python 2.7, 3.5+, and PyPy/PyPy3 7.3 are supported with an - Python 3.5+, and PyPy3 7.3 are supported with an implementation-agnostic
implementation-agnostic interface. interface (pybind11 2.9 was the last version to support Python 2).
- It is possible to bind C++11 lambda functions with captured - It is possible to bind C++11 lambda functions with captured
variables. The lambda capture data is stored inside the resulting variables. The lambda capture data is stored inside the resulting
......
...@@ -18,5 +18,4 @@ ALIASES += "endrst=\endverbatim" ...@@ -18,5 +18,4 @@ ALIASES += "endrst=\endverbatim"
QUIET = YES QUIET = YES
WARNINGS = YES WARNINGS = YES
WARN_IF_UNDOCUMENTED = NO WARN_IF_UNDOCUMENTED = NO
PREDEFINED = PY_MAJOR_VERSION=3 \ PREDEFINED = PYBIND11_NOINLINE
PYBIND11_NOINLINE
Strings, bytes and Unicode conversions 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++ Passing Python strings to C++
============================= =============================
...@@ -58,9 +50,9 @@ Passing bytes to C++ ...@@ -58,9 +50,9 @@ Passing bytes to C++
-------------------- --------------------
A Python ``bytes`` object will be passed to C++ functions that accept A Python ``bytes`` object will be passed to C++ functions that accept
``std::string`` or ``char*`` *without* conversion. On Python 3, in order to ``std::string`` or ``char*`` *without* conversion. In order to make a function
make a function *only* accept ``bytes`` (and not ``str``), declare it as taking *only* accept ``bytes`` (and not ``str``), declare it as taking a ``py::bytes``
a ``py::bytes`` argument. argument.
Returning C++ strings to Python Returning C++ strings to Python
...@@ -204,11 +196,6 @@ decoded to Python ``str``. ...@@ -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 Strings in multibyte encodings such as Shift-JIS must transcoded to a
UTF-8/16/32 before being returned to Python. UTF-8/16/32 before being returned to Python.
......
...@@ -133,14 +133,14 @@ a virtual method call. ...@@ -133,14 +133,14 @@ a virtual method call.
>>> from example import * >>> from example import *
>>> d = Dog() >>> d = Dog()
>>> call_go(d) >>> call_go(d)
u'woof! woof! woof! ' 'woof! woof! woof! '
>>> class Cat(Animal): >>> class Cat(Animal):
... def go(self, n_times): ... def go(self, n_times):
... return "meow! " * n_times ... return "meow! " * n_times
... ...
>>> c = Cat() >>> c = Cat()
>>> call_go(c) >>> call_go(c)
u'meow! meow! meow! ' 'meow! meow! meow! '
If you are defining a custom constructor in a derived Python class, you *must* 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__``, ensure that you explicitly call the bound C++ constructor using ``__init__``,
...@@ -813,26 +813,21 @@ An instance can now be pickled as follows: ...@@ -813,26 +813,21 @@ An instance can now be pickled as follows:
.. code-block:: python .. code-block:: python
try: import pickle
import cPickle as pickle # Use cPickle on Python 2.7
except ImportError:
import pickle
p = Pickleable("test_value") p = Pickleable("test_value")
p.setExtra(15) p.setExtra(15)
data = pickle.dumps(p, 2) data = pickle.dumps(p)
.. note:: .. note::
Note that only the cPickle module is supported on Python 2.7. 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
The second argument to ``dumps`` is also crucial: it selects the pickle always use the latest available version. Beware: failure to follow these
protocol version 2, since the older version 1 is not supported. Newer instructions will cause important pybind11 memory allocation routines to be
versions are also fine—for instance, specify ``-1`` to always use the skipped during unpickling, which will likely lead to memory corruption
latest available version. Beware: failure to follow these instructions and/or segmentation faults. Python defaults to version 3 (Python 3-3.7) and
will cause important pybind11 memory allocation routines to be skipped version 4 for Python 3.8+.
during unpickling, which will likely lead to memory corruption and/or
segmentation faults.
.. seealso:: .. seealso::
...@@ -849,11 +844,9 @@ Python normally uses references in assignments. Sometimes a real copy is needed ...@@ -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 to prevent changing all copies. The ``copy`` module [#f5]_ provides these
capabilities. 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 compatible. However, performance can be improved by adding custom
``__copy__`` and ``__deepcopy__`` methods. With Python 2.7, these custom methods ``__copy__`` and ``__deepcopy__`` methods.
are mandatory for (deep)copy compatibility, because pybind11 only supports
cPickle.
For simple classes (deep)copy can be enabled by using the copy constructor, For simple classes (deep)copy can be enabled by using the copy constructor,
which should look as follows: which should look as follows:
......
...@@ -328,8 +328,8 @@ an invalid state. ...@@ -328,8 +328,8 @@ an invalid state.
Chaining exceptions ('raise from') Chaining exceptions ('raise from')
================================== ==================================
In Python 3.3 a mechanism for indicating that exceptions were caused by other Python has a mechanism for indicating that exceptions were caused by other
exceptions was introduced: exceptions:
.. code-block:: py .. code-block:: py
...@@ -340,7 +340,7 @@ exceptions was introduced: ...@@ -340,7 +340,7 @@ exceptions was introduced:
To do a similar thing in pybind11, you can use the ``py::raise_from`` function. It 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 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 .. code-block:: cpp
......
...@@ -398,8 +398,6 @@ Ellipsis ...@@ -398,8 +398,6 @@ Ellipsis
Python 3 provides a convenient ``...`` ellipsis notation that is often used to Python 3 provides a convenient ``...`` ellipsis notation that is often used to
slice multidimensional arrays. For instance, the following snippet extracts the slice multidimensional arrays. For instance, the following snippet extracts the
middle dimensions of a tensor with the first and last index set to zero. middle dimensions of a tensor with the first and last index set to zero.
In Python 2, the syntactic sugar ``...`` is not available, but the singleton
``Ellipsis`` (of type ``ellipsis``) can still be used directly.
.. code-block:: python .. code-block:: python
...@@ -414,8 +412,6 @@ operation on the C++ side: ...@@ -414,8 +412,6 @@ operation on the C++ side:
py::array a = /* A NumPy array */; py::array a = /* A NumPy array */;
py::array b = a[py::make_tuple(0, py::ellipsis(), 0)]; 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 Memory view
=========== ===========
...@@ -455,9 +451,5 @@ We can also use ``memoryview::from_memory`` for a simple 1D contiguous buffer: ...@@ -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 .. versionchanged:: 2.6
``memoryview::from_memory`` added. ``memoryview::from_memory`` added.
...@@ -166,12 +166,12 @@ load and execute the example: ...@@ -166,12 +166,12 @@ load and execute the example:
.. code-block:: pycon .. code-block:: pycon
$ python $ python
Python 2.7.10 (default, Aug 22 2015, 20:33:39) Python 3.9.10 (main, Jan 15 2022, 11:48:04)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.1)] on darwin [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information. Type "help", "copyright", "credits" or "license" for more information.
>>> import example >>> import example
>>> example.add(1, 2) >>> example.add(1, 2)
3L 3
>>> >>>
.. _keyword_args: .. _keyword_args:
......
# -*- coding: utf-8 -*-
import datetime as dt import datetime as dt
import os import os
import random import random
...@@ -75,7 +74,7 @@ def generate_dummy_code_boost(nclasses=10): ...@@ -75,7 +74,7 @@ def generate_dummy_code_boost(nclasses=10):
for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]: for codegen in [generate_dummy_code_pybind11, generate_dummy_code_boost]:
print("{") print("{")
for i in range(0, 10): for i in range(0, 10):
nclasses = 2 ** i nclasses = 2**i
with open("test.cpp", "w") as f: with open("test.cpp", "w") as f:
f.write(codegen(nclasses)) f.write(codegen(nclasses))
n1 = dt.datetime.now() n1 = dt.datetime.now()
......
...@@ -48,10 +48,10 @@ interactive Python session demonstrating this example is shown below: ...@@ -48,10 +48,10 @@ interactive Python session demonstrating this example is shown below:
>>> print(p) >>> print(p)
<example.Pet object at 0x10cd98060> <example.Pet object at 0x10cd98060>
>>> p.getName() >>> p.getName()
u'Molly' 'Molly'
>>> p.setName("Charly") >>> p.setName("Charly")
>>> p.getName() >>> p.getName()
u'Charly' 'Charly'
.. seealso:: .. seealso::
...@@ -124,10 +124,10 @@ This makes it possible to write ...@@ -124,10 +124,10 @@ This makes it possible to write
>>> p = example.Pet("Molly") >>> p = example.Pet("Molly")
>>> p.name >>> p.name
u'Molly' 'Molly'
>>> p.name = "Charly" >>> p.name = "Charly"
>>> p.name >>> p.name
u'Charly' 'Charly'
Now suppose that ``Pet::name`` was a private internal variable Now suppose that ``Pet::name`` was a private internal variable
that can only be accessed via setters and getters. that can only be accessed via setters and getters.
...@@ -282,9 +282,9 @@ expose fields and methods of both types: ...@@ -282,9 +282,9 @@ expose fields and methods of both types:
>>> p = example.Dog("Molly") >>> p = example.Dog("Molly")
>>> p.name >>> p.name
u'Molly' 'Molly'
>>> p.bark() >>> p.bark()
u'woof!' 'woof!'
The C++ classes defined above are regular non-polymorphic types with an The C++ classes defined above are regular non-polymorphic types with an
inheritance relationship. This is reflected in Python: inheritance relationship. This is reflected in Python:
...@@ -332,7 +332,7 @@ will automatically recognize this: ...@@ -332,7 +332,7 @@ will automatically recognize this:
>>> type(p) >>> type(p)
PolymorphicDog # automatically downcast PolymorphicDog # automatically downcast
>>> p.bark() >>> p.bark()
u'woof!' 'woof!'
Given a pointer to a polymorphic base, pybind11 performs automatic downcasting 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 to the actual derived type. Note that this goes beyond the usual situation in
......
...@@ -462,11 +462,8 @@ available in all modes. The targets provided are: ...@@ -462,11 +462,8 @@ available in all modes. The targets provided are:
``pybind11::headers`` ``pybind11::headers``
Just the pybind11 headers and minimum compile requirements 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`` ``pybind11::pybind11``
Python headers + ``pybind11::headers`` + ``pybind11::python2_no_register`` (Python 2 only) Python headers + ``pybind11::headers``
``pybind11::python_link_helper`` ``pybind11::python_link_helper``
Just the "linking" part of pybind11:module Just the "linking" part of pybind11:module
...@@ -577,21 +574,12 @@ On Linux, you can compile an example such as the one given in ...@@ -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) $ 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 The ``python3 -m pybind11 --includes`` command fetches the include paths for
both pybind11 and Python headers. This assumes that pybind11 has been installed 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 using ``pip`` or ``conda``. If it hasn't, you can also manually specify
``-I <path-to-pybind11>/include`` together with the Python includes path ``-I <path-to-pybind11>/include`` together with the Python includes path
``python3-config --includes``. ``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 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 the ``-undefined dynamic_lookup`` flag so as to ignore missing symbols when
building the module: building the module:
......
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# #
# pybind11 documentation build configuration file, created by # pybind11 documentation build configuration file, created by
# sphinx-quickstart on Sun Oct 11 19:23:48 2015. # sphinx-quickstart on Sun Oct 11 19:23:48 2015.
......
...@@ -8,9 +8,7 @@ Frequently asked questions ...@@ -8,9 +8,7 @@ Frequently asked questions
filename of the extension library (without suffixes such as ``.so``). filename of the extension library (without suffixes such as ``.so``).
2. If the above did not fix the issue, you are likely using an incompatible 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 version of Python that does not match what you compiled with.
Python 2, while the interpreter is running on top of some version of Python
3, or vice versa).
"Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``" "Symbol not found: ``__Py_ZeroStruct`` / ``_PyInstanceMethod_Type``"
======================================================================== ========================================================================
...@@ -289,27 +287,7 @@ Conflicts can arise, however, when using pybind11 in a project that *also* uses ...@@ -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. the CMake Python detection in a system with several Python versions installed.
This difference may cause inconsistencies and errors if *both* mechanisms are This difference may cause inconsistencies and errors if *both* mechanisms are
used in the same project. Consider the following CMake code executed in a used in the same project.
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.
There are three possible solutions: There are three possible solutions:
......
...@@ -325,7 +325,7 @@ public: ...@@ -325,7 +325,7 @@ public:
res = 0; // None is implicitly converted to False res = 0; // None is implicitly converted to False
} }
#if defined(PYPY_VERSION) #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)) { else if (hasattr(src, PYBIND11_BOOL_ATTR)) {
res = PyObject_IsTrue(src.ptr()); res = PyObject_IsTrue(src.ptr());
} }
...@@ -375,37 +375,16 @@ struct string_caster { ...@@ -375,37 +375,16 @@ struct string_caster {
static constexpr size_t UTF_N = 8 * sizeof(CharT); static constexpr size_t UTF_N = 8 * sizeof(CharT);
bool load(handle src, bool) { bool load(handle src, bool) {
#if PY_MAJOR_VERSION < 3
object temp;
#endif
handle load_src = src; handle load_src = src;
if (!src) { if (!src) {
return false; return false;
} }
if (!PyUnicode_Check(load_src.ptr())) { if (!PyUnicode_Check(load_src.ptr())) {
#if PY_MAJOR_VERSION >= 3
return load_bytes(load_src); 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 // For UTF-8 we avoid the need for a temporary `bytes` object by using
// On Python >= 3.3, for UTF-8 we avoid the need for a temporary `bytes` // `PyUnicode_AsUTF8AndSize`.
// object by using `PyUnicode_AsUTF8AndSize`.
if (PYBIND11_SILENCE_MSVC_C4127(UTF_N == 8)) { if (PYBIND11_SILENCE_MSVC_C4127(UTF_N == 8)) {
Py_ssize_t size = -1; Py_ssize_t size = -1;
const auto *buffer const auto *buffer
...@@ -417,7 +396,6 @@ struct string_caster { ...@@ -417,7 +396,6 @@ struct string_caster {
value = StringType(buffer, static_cast<size_t>(size)); value = StringType(buffer, static_cast<size_t>(size));
return true; return true;
} }
#endif
auto utfNbytes auto utfNbytes
= reinterpret_steal<object>(PyUnicode_AsEncodedString(load_src.ptr(), = reinterpret_steal<object>(PyUnicode_AsEncodedString(load_src.ptr(),
...@@ -486,7 +464,7 @@ private: ...@@ -486,7 +464,7 @@ private:
template <typename C = CharT> template <typename C = CharT>
bool load_bytes(enable_if_t<std::is_same<C, char>::value, handle> src) { bool load_bytes(enable_if_t<std::is_same<C, char>::value, handle> src) {
if (PYBIND11_BYTES_CHECK(src.ptr())) { 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. // without any encoding attempt.
const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr()); const char *bytes = PYBIND11_BYTES_AS_STRING(src.ptr());
if (bytes) { if (bytes) {
...@@ -922,18 +900,6 @@ struct pyobject_caster { ...@@ -922,18 +900,6 @@ struct pyobject_caster {
template <typename T = type, enable_if_t<std::is_base_of<object, T>::value, int> = 0> template <typename T = type, enable_if_t<std::is_base_of<object, T>::value, int> = 0>
bool load(handle src, bool /* convert */) { 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)) { if (!isinstance<type>(src)) {
return false; return false;
} }
...@@ -1313,7 +1279,7 @@ public: ...@@ -1313,7 +1279,7 @@ public:
/// \ingroup annotations /// \ingroup annotations
/// Annotation indicating that all following arguments are keyword-only; the is the equivalent of /// 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 {}; struct kw_only {};
/// \ingroup annotations /// \ingroup annotations
......
...@@ -15,12 +15,12 @@ ...@@ -15,12 +15,12 @@
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
#if PY_VERSION_HEX >= 0x03030000 && !defined(PYPY_VERSION) #if !defined(PYPY_VERSION)
# define PYBIND11_BUILTIN_QUALNAME # define PYBIND11_BUILTIN_QUALNAME
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) # define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj)
#else #else
// In pre-3.3 Python, we still set __qualname__ so that we can produce reliable function type // In PyPy, we still set __qualname__ so that we can produce reliable function type
// signatures; in 3.3+ this macro expands to nothing: // signatures; in CPython this macro expands to nothing:
# define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) \ # define PYBIND11_SET_OLDPY_QUALNAME(obj, nameobj) \
setattr((PyObject *) obj, "__qualname__", nameobj) setattr((PyObject *) obj, "__qualname__", nameobj)
#endif #endif
...@@ -155,7 +155,6 @@ extern "C" inline int pybind11_meta_setattro(PyObject *obj, PyObject *name, PyOb ...@@ -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 * 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, * 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 ...@@ -170,7 +169,6 @@ extern "C" inline PyObject *pybind11_meta_getattro(PyObject *obj, PyObject *name
} }
return PyType_Type.tp_getattro(obj, name); return PyType_Type.tp_getattro(obj, name);
} }
#endif
/// metaclass `__call__` function that is used to create all pybind11 objects. /// metaclass `__call__` function that is used to create all pybind11 objects.
extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, PyObject *kwargs) { extern "C" inline PyObject *pybind11_meta_call(PyObject *type, PyObject *args, PyObject *kwargs) {
...@@ -266,9 +264,7 @@ inline PyTypeObject *make_default_metaclass() { ...@@ -266,9 +264,7 @@ inline PyTypeObject *make_default_metaclass() {
type->tp_call = pybind11_meta_call; type->tp_call = pybind11_meta_call;
type->tp_setattro = pybind11_meta_setattro; type->tp_setattro = pybind11_meta_setattro;
#if PY_MAJOR_VERSION >= 3
type->tp_getattro = pybind11_meta_getattro; type->tp_getattro = pybind11_meta_getattro;
#endif
type->tp_dealloc = pybind11_meta_dealloc; type->tp_dealloc = pybind11_meta_dealloc;
...@@ -613,9 +609,6 @@ extern "C" inline void pybind11_releasebuffer(PyObject *, Py_buffer *view) { ...@@ -613,9 +609,6 @@ extern "C" inline void pybind11_releasebuffer(PyObject *, Py_buffer *view) {
/// Give this type a buffer interface. /// Give this type a buffer interface.
inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) { inline void enable_buffer_protocol(PyHeapTypeObject *heap_type) {
heap_type->ht_type.tp_as_buffer = &heap_type->as_buffer; 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_getbuffer = pybind11_getbuffer;
heap_type->as_buffer.bf_releasebuffer = pybind11_releasebuffer; heap_type->as_buffer.bf_releasebuffer = pybind11_releasebuffer;
...@@ -628,12 +621,8 @@ inline PyObject *make_new_python_type(const type_record &rec) { ...@@ -628,12 +621,8 @@ inline PyObject *make_new_python_type(const type_record &rec) {
auto qualname = name; auto qualname = name;
if (rec.scope && !PyModule_Check(rec.scope.ptr()) && hasattr(rec.scope, "__qualname__")) { if (rec.scope && !PyModule_Check(rec.scope.ptr()) && hasattr(rec.scope, "__qualname__")) {
#if PY_MAJOR_VERSION >= 3
qualname = reinterpret_steal<object>( qualname = reinterpret_steal<object>(
PyUnicode_FromFormat("%U.%U", rec.scope.attr("__qualname__").ptr(), name.ptr())); 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_; object module_;
...@@ -697,15 +686,10 @@ inline PyObject *make_new_python_type(const type_record &rec) { ...@@ -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_number = &heap_type->as_number;
type->tp_as_sequence = &heap_type->as_sequence; type->tp_as_sequence = &heap_type->as_sequence;
type->tp_as_mapping = &heap_type->as_mapping; type->tp_as_mapping = &heap_type->as_mapping;
#if PY_VERSION_HEX >= 0x03050000
type->tp_as_async = &heap_type->as_async; type->tp_as_async = &heap_type->as_async;
#endif
/* Flags */ /* Flags */
type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE; type->tp_flags |= Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HEAPTYPE;
#if PY_MAJOR_VERSION < 3
type->tp_flags |= Py_TPFLAGS_CHECKTYPES;
#endif
if (!rec.is_final) { if (!rec.is_final) {
type->tp_flags |= Py_TPFLAGS_BASETYPE; type->tp_flags |= Py_TPFLAGS_BASETYPE;
} }
......
...@@ -211,6 +211,9 @@ ...@@ -211,6 +211,9 @@
#endif #endif
#include <Python.h> #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 <frameobject.h>
#include <pythread.h> #include <pythread.h>
...@@ -266,69 +269,37 @@ ...@@ -266,69 +269,37 @@
// If UNDEFINED, pybind11::str can only hold PyUnicodeObject, and // If UNDEFINED, pybind11::str can only hold PyUnicodeObject, and
// pybind11::isinstance<str>() is true only for pybind11::str. // pybind11::isinstance<str>() is true only for pybind11::str.
// However, for Python 2 only (!), the pybind11::str caster // 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 // the transition from the legacy behavior to the non-permissive
// behavior. // behavior.
#if PY_MAJOR_VERSION >= 3 /// Compatibility macros for various Python versions /// Compatibility macros for Python 2 / Python 3 versions TODO: remove
# define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr) #define PYBIND11_INSTANCE_METHOD_NEW(ptr, class_) PyInstanceMethod_New(ptr)
# define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check #define PYBIND11_INSTANCE_METHOD_CHECK PyInstanceMethod_Check
# define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION #define PYBIND11_INSTANCE_METHOD_GET_FUNCTION PyInstanceMethod_GET_FUNCTION
# define PYBIND11_BYTES_CHECK PyBytes_Check #define PYBIND11_BYTES_CHECK PyBytes_Check
# define PYBIND11_BYTES_FROM_STRING PyBytes_FromString #define PYBIND11_BYTES_FROM_STRING PyBytes_FromString
# define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize #define PYBIND11_BYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize
# define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize #define PYBIND11_BYTES_AS_STRING_AND_SIZE PyBytes_AsStringAndSize
# define PYBIND11_BYTES_AS_STRING PyBytes_AsString #define PYBIND11_BYTES_AS_STRING PyBytes_AsString
# define PYBIND11_BYTES_SIZE PyBytes_Size #define PYBIND11_BYTES_SIZE PyBytes_Size
# define PYBIND11_LONG_CHECK(o) PyLong_Check(o) #define PYBIND11_LONG_CHECK(o) PyLong_Check(o)
# define PYBIND11_LONG_AS_LONGLONG(o) PyLong_AsLongLong(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_SIGNED(o) PyLong_FromSsize_t((ssize_t) (o))
# define PYBIND11_LONG_FROM_UNSIGNED(o) PyLong_FromSize_t((size_t) (o)) #define PYBIND11_LONG_FROM_UNSIGNED(o) PyLong_FromSize_t((size_t) (o))
# define PYBIND11_BYTES_NAME "bytes" #define PYBIND11_BYTES_NAME "bytes"
# define PYBIND11_STRING_NAME "str" #define PYBIND11_STRING_NAME "str"
# define PYBIND11_SLICE_OBJECT PyObject #define PYBIND11_SLICE_OBJECT PyObject
# define PYBIND11_FROM_STRING PyUnicode_FromString #define PYBIND11_FROM_STRING PyUnicode_FromString
# define PYBIND11_STR_TYPE ::pybind11::str #define PYBIND11_STR_TYPE ::pybind11::str
# define PYBIND11_BOOL_ATTR "__bool__" #define PYBIND11_BOOL_ATTR "__bool__"
# define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_bool) #define PYBIND11_NB_BOOL(ptr) ((ptr)->nb_bool)
# define PYBIND11_BUILTINS_MODULE "builtins" #define PYBIND11_BUILTINS_MODULE "builtins"
// Providing a separate declaration to make Clang's -Wmissing-prototypes happy. // Providing a separate declaration to make Clang's -Wmissing-prototypes happy.
// See comment for PYBIND11_MODULE below for why this is marked "maybe unused". // 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_MAYBE_UNUSED PYBIND11_EXPORT PyObject *PyInit_##name(); \
extern "C" 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 #if PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03050200
extern "C" { extern "C" {
...@@ -362,31 +333,15 @@ PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current; ...@@ -362,31 +333,15 @@ PyAPI_DATA(_Py_atomic_address) _PyThreadState_Current;
} \ } \
} }
#if PY_VERSION_HEX >= 0x03030000 #define PYBIND11_CATCH_INIT_EXCEPTIONS \
catch (pybind11::error_already_set & e) { \
# define PYBIND11_CATCH_INIT_EXCEPTIONS \ pybind11::raise_from(e, PyExc_ImportError, "initialization failed"); \
catch (pybind11::error_already_set & e) { \ return nullptr; \
pybind11::raise_from(e, PyExc_ImportError, "initialization failed"); \ } \
return nullptr; \ catch (const std::exception &e) { \
} \ PyErr_SetString(PyExc_ImportError, e.what()); \
catch (const std::exception &e) { \ return nullptr; \
PyErr_SetString(PyExc_ImportError, e.what()); \ }
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 /** \rst
***Deprecated in favor of PYBIND11_MODULE*** ***Deprecated in favor of PYBIND11_MODULE***
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment