feat!: drop support for Python 3.8, MSVC 2017 (#6110)
* feat!: drop support for Python 3.8
The minimum supported version is now Python 3.9. pybind11 v3.0 was the last
release that supports Python 3.8. The deprecation note said that support goes
away in 3.1.
Remove the code paths that this makes dead:
- the `_PyObject_Vectorcall` fallback in `cast.h`
- the `frame->f_code` and `frame->f_back` fallbacks in `pytypes.h`
- the `PyFrame_FastToLocals` path in `get_type_override`
- the conditional `Py_VISIT(Py_TYPE(self))` in `tp_traverse`
- `PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX`, the pre-PyConfig interpreter
init, and the `widen_chars` helpers in `embed.h`
Assisted-by: ClaudeCode:claude-opus-5
* ci(appveyor): use Python 3.9
The AppVeyor job set `PYTHON: 38`, which makes the path `C:\Python38`.
The image gives Python 3.9.13 as `C:\Python39`.
Assisted-by: ClaudeCode:claude-opus-5
* feat!: require MSVC 2019 or newer
Python 3.9 is the new minimum, so MSVC 2017 is no longer needed. Raise the
compile-time floor to _MSC_VER 1920 and remove the workarounds that only
applied below it: std::launder, fold expressions, weak_from_this, aligned
new/delete, the C4100 warning helper, and the func_handle syntax error.
AppVeyor now builds with Visual Studio 2019.
Assisted-by: ClaudeCode:claude-opus-5
* fix(appveyor): build against the Python that has the test packages
CMake 4 has no FindPythonLibs, so pybind11 uses FindPython. FindPython reads
the registry before PATH and selected `C:\Python314-x64`, but the test packages
go into the Python on PATH. Pass `Python_ROOT_DIR` to name the correct one.
Also set `CMAKE_ARCH`. It was never set, so the architecture came from the
generator. Visual Studio 2017 defaults to Win32, but Visual Studio 2019
defaults to x64, which made this x86 job build 64-bit code.
Assisted-by: ClaudeCode:claude-opus-5
* fix(appveyor): give the linker Python's libs directory
The build compiled but failed to link with LNK1104 on a bare `python39.lib`.
That name comes from the `#pragma comment(lib, ...)` in pyconfig.h, so the
linker needs the directory. CMake 4 has no FindPythonLibs, and FindPython does
not add it for this Debug x86 build. Put it on LIB instead.
The directory listing is temporary, to confirm the library is present.
Assisted-by: ClaudeCode:claude-opus-5
* fix(appveyor): link the release Python library in Debug
The image ships python39_d.lib next to python39.lib, so FindPython picks the
debug import library for a Debug build. pybind11 undefines _DEBUG around
Python.h, so pyconfig.h asks for python39.lib instead and the link failed with
LNK1104. Name the release library for the debug slot.
Setting LIB does not work, because MSBuild replaces it from the toolset, and it
would link both import libraries.
Assisted-by: ClaudeCode:claude-opus-5
* chore(appveyor): print link settings to debug LNK1104
Revert the two attempted fixes. Neither changed the failure: setting LIB does
not survive MSBuild, and naming the release library for Python_LIBRARY_DEBUG
had no effect.
Print the Python cache entries and the link settings of a generated project
file instead, to see what the linker really gets. Temporary.
Assisted-by: ClaudeCode:claude-opus-5
* fix(appveyor): take the release Python library in Debug
The generated project file linked C:\Python39\libs\python39_d.lib in the Debug
configuration, because the image ships debug binaries next to the release ones.
pybind11 undefines _DEBUG around Python.h, so pyconfig.h asks for python39.lib
in a #pragma comment(lib), which nothing on the link line satisfies and no
library directory holds. Map Debug to the release artifacts.
Assisted-by: ClaudeCode:claude-opus-5
* chore(appveyor): drop the temporary link diagnostic
Assisted-by: ClaudeCode:claude-opus-5
* fix(tests): guard the unraisable warning filter for pytest < 6
The distro pytest in the Clang and GCC Docker jobs has no
PytestUnraisableExceptionWarning, so an unconditional filterwarnings
mark makes pytest fail with an INTERNALERROR after the tests pass.
Assisted-by: ClaudeCode:claude-opus-5
Claude-Session: https://claude.ai/code/session_01Aimf6HuSz1vLRwBnbxmCTc
* docs: address review items on version hints, embed docs, and a PyPy xfail
Extend Python_ADDITIONAL_VERSIONS through 3.15, describe the PyConfig
behavior of initialize_interpreter, and drop the stale Python 3.8 wording
from the PyPy xfail reason.
Assisted-by: ClaudeCode:claude-opus-5
* Update README.rst
Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com>
---------
Co-authored-by: Ralf W. Grosse-Kunstleve <rwgkio@gmail.com>
diff --git a/.appveyor.yml b/.appveyor.yml
index 391cf10..8429d5e 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,6 +1,6 @@
version: 1.0.{build}
image:
-- Visual Studio 2017
+- Visual Studio 2019
test: off
skip_branch_with_pr: true
build:
@@ -9,13 +9,20 @@
- x86
environment:
matrix:
- - PYTHON: 38
+ - PYTHON: 39
CONFIG: Debug
install:
- ps: |
- $env:CMAKE_GENERATOR = "Visual Studio 15 2017"
- if ($env:PLATFORM -eq "x64") { $env:PYTHON = "$env:PYTHON-x64" }
- $env:PATH = "C:\Python$env:PYTHON\;C:\Python$env:PYTHON\Scripts\;$env:PATH"
+ $env:CMAKE_GENERATOR = "Visual Studio 16 2019"
+ # The 2019 generator defaults to x64, so name the architecture explicitly.
+ if ($env:PLATFORM -eq "x64") {
+ $env:PYTHON = "$env:PYTHON-x64"
+ $env:CMAKE_ARCH = "x64"
+ } else {
+ $env:CMAKE_ARCH = "Win32"
+ }
+ $env:PYTHON_ROOT = "C:\Python$env:PYTHON"
+ $env:PATH = "$env:PYTHON_ROOT\;$env:PYTHON_ROOT\Scripts\;$env:PATH"
python -W ignore -m pip install --upgrade pip wheel
python -W ignore -m pip install pytest numpy --no-warn-script-location pytest-timeout
- ps: |
@@ -23,7 +30,15 @@
7z x eigen-3.3.7.zip -y > $null
$env:CMAKE_INCLUDE_PATH = "eigen-3.3.7;$env:CMAKE_INCLUDE_PATH"
build_script:
+# FindPython looks at the registry before PATH, so it picks the newest Python on
+# the image. Point it at the one that has the test packages.
+#
+# The image also has python39_d.lib, which FindPython uses for a Debug build.
+# pybind11 undefines _DEBUG around Python.h, so pyconfig.h asks for python39.lib
+# and the link fails. Take the release library in Debug too.
- cmake -G "%CMAKE_GENERATOR%" -A "%CMAKE_ARCH%"
+ -DPython_ROOT_DIR="%PYTHON_ROOT%"
+ -DCMAKE_MAP_IMPORTED_CONFIG_DEBUG=Release
-DCMAKE_CXX_STANDARD=14
-DPYBIND11_WERROR=ON
-DDOWNLOAD_CATCH=ON
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d27c87a..eb2fcf2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -39,7 +39,7 @@
matrix:
include:
- runs-on: ubuntu-22.04
- python-version: '3.8'
+ python-version: '3.9'
cmake-args: -DPYBIND11_FINDPYTHON=OFF -DPYBIND11_NUMPY_1_ONLY=ON
- runs-on: ubuntu-latest
python-version: '3.13'
@@ -60,7 +60,7 @@
python-version: '3.14'
cmake-args: -DCMAKE_CXX_STANDARD=14
- runs-on: windows-2022
- python-version: '3.8'
+ python-version: '3.9'
cmake-args: -DPYBIND11_FINDPYTHON=OFF
@@ -78,7 +78,7 @@
matrix:
include:
- runs-on: ubuntu-latest
- python-version: '3.8'
+ python-version: '3.9'
cmake-args: -DPYBIND11_FINDPYTHON=ON -DCMAKE_CXX_STANDARD=17
- runs-on: ubuntu-latest
python-version: '3.10'
@@ -95,7 +95,7 @@
# No SciPy for macOS ARM
- runs-on: macos-15-intel
- python-version: '3.8'
+ python-version: '3.9'
cmake-args: -DCMAKE_CXX_STANDARD=14
- runs-on: macos-15-intel
python-version: '3.13'
@@ -118,7 +118,7 @@
python-version: '3.9'
cmake-args: -DPYBIND11_TEST_SMART_HOLDER=ON
- runs-on: windows-2022
- python-version: '3.8'
+ python-version: '3.9'
cmake-args: -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded -DPYBIND11_NUMPY_1_ONLY=ON
# This needs a python built with MTd
# - runs-on: windows-2022
@@ -187,7 +187,7 @@
- name: Prepare env
run: uv pip install --python=python --system -r tests/requirements.txt
- # TODO Resolve Windows Ninja shared object issue on Python 3.8+
+ # TODO Resolve Windows Ninja shared object issue on Python 3.9+
- name: Use Ninja except on Windows
if: runner.os != 'Windows'
run: echo "CMAKE_GENERATOR=Ninja" >> "$GITHUB_ENV"
@@ -631,9 +631,9 @@
- name: Latest actions/checkout
uses: actions/checkout@v7
- - name: Add Python 3.8
+ - name: Add Python 3.9
if: matrix.container == 'almalinux:8'
- run: dnf update -y && dnf install -y python38-devel gcc-c++ make git
+ run: dnf update -y && dnf install -y python39-devel gcc-c++ make git
- name: Add Python 3 (default)
if: matrix.container != 'almalinux:8'
@@ -769,7 +769,7 @@
fail-fast: false
matrix:
include:
- - python: '3.8'
+ - python: '3.9'
args: -DCMAKE_CXX_STANDARD=17
- python: '3.13'
diff --git a/.github/workflows/pip.yml b/.github/workflows/pip.yml
index d672971..97f8cd2 100644
--- a/.github/workflows/pip.yml
+++ b/.github/workflows/pip.yml
@@ -19,16 +19,16 @@
# This builds the sdists and wheels and makes sure the files are exactly as
# expected.
test-packaging:
- name: π 3.8 • π¦ tests • windows-latest
+ name: π 3.9 • π¦ tests • windows-latest
runs-on: windows-latest
steps:
- uses: actions/checkout@v7
- - name: Setup π 3.8
+ - name: Setup π 3.9
uses: actions/setup-python@v7
with:
- python-version: 3.8
+ python-version: 3.9
- name: Install uv
uses: astral-sh/setup-uv@v9.0.0
@@ -43,16 +43,16 @@
# This runs the packaging tests and also builds and saves the packages as
# artifacts.
packaging:
- name: π 3.8 • π¦ & π¦ tests • ubuntu-latest
+ name: π 3.9 • π¦ & π¦ tests • ubuntu-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- - name: Setup π 3.8
+ - name: Setup π 3.9
uses: actions/setup-python@v7
with:
- python-version: 3.8
+ python-version: 3.9
- name: Install uv
uses: astral-sh/setup-uv@v9.0.0
diff --git a/.github/workflows/reusable-standard.yml b/.github/workflows/reusable-standard.yml
index 1b40210..326c201 100644
--- a/.github/workflows/reusable-standard.yml
+++ b/.github/workflows/reusable-standard.yml
@@ -63,7 +63,7 @@
if: runner.os == 'Linux'
run: uv pip install --python=python --system pytest-github-actions-annotate-failures
- # TODO Resolve Windows Ninja shared object issue on Python 3.8+
+ # TODO Resolve Windows Ninja shared object issue on Python 3.9+
- name: Use Ninja except on Windows
if: runner.os != 'Windows'
run: echo "CMAKE_GENERATOR=Ninja" >> "$GITHUB_ENV"
diff --git a/AGENTS.md b/AGENTS.md
index d3e0985..4108925 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -95,5 +95,5 @@
- Any new functionality needs a test (add to or create the paired `.cpp`/`.py` in `tests/`, and register the test in `tests/CMakeLists.txt`).
- Bug fixes should be paired with new tests that fail without the fix.
- Try to add to an existing test file if possible (more files slow down tests)
-- Default C++ standard follows the consumer's toolchain; CI exercises a wide matrix (CPython 3.8+, PyPy, GraalPy; multiple compilers and C++ standards). Keep changes portable across that matrix.
+- Default C++ standard follows the consumer's toolchain; CI exercises a wide matrix (CPython 3.9+, PyPy, GraalPy; multiple compilers and C++ standards). Keep changes portable across that matrix.
- PR descriptions follow a template, the key part is under "Suggested changelog entry", which is how we generate our changelog (with `nox -s make_changelog`)
diff --git a/README.rst b/README.rst
index 26d618f..c68f03b 100644
--- a/README.rst
+++ b/README.rst
@@ -36,7 +36,7 @@
Think of this library as a tiny self-contained version of Boost.Python
with everything stripped away that isn't relevant for binding
generation. Without comments, the core header files only require ~4K
-lines of code and depend on Python (CPython 3.8+, PyPy, or GraalPy) and the C++
+lines of code and depend on Python (CPython 3.9+, PyPy, or GraalPy) and the C++
standard library. This compact implementation was possible thanks to some C++11
language features (specifically: tuples, lambda functions and variadic
templates). Since its creation, this library has grown beyond Boost.Python in
@@ -81,7 +81,7 @@
In addition to the core functionality, pybind11 provides some extra
goodies:
-- CPython 3.8+, PyPy3 7.3.17+, and GraalPy 24.1+ are supported with an
+- CPython 3.9+, PyPy3 7.3.17+, and GraalPy 24.1+ are supported with an
implementation-agnostic interface (see older versions for older CPython
and PyPy versions).
@@ -127,7 +127,7 @@
systems, Python versions, C++ standards, and toolchains. For an up-to-date
view of the combinations we currently test, please see the
`pybind11 GitHub Actions <https://github.com/pybind/pybind11/actions?query=branch%3Amaster>`_
-logs.
+and `AppVeyor <https://ci.appveyor.com/project/wjakob/pybind11>`_ logs.
The test matrix naturally evolves over time as older platforms and compilers
fall out of use and new ones are added by the community. Closely related
diff --git a/docs/advanced/classes.rst b/docs/advanced/classes.rst
index bfbaea6..2954411 100644
--- a/docs/advanced/classes.rst
+++ b/docs/advanced/classes.rst
@@ -1400,10 +1400,8 @@
auto *type = &heap_type->ht_type;
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
type->tp_traverse = [](PyObject *self_base, visitproc visit, void *arg) {
- // https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
- #if PY_VERSION_HEX >= 0x03090000
+ // https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
Py_VISIT(Py_TYPE(self_base));
- #endif
if (py::detail::is_holder_constructed(self_base)) {
auto &self = py::cast<ContainerOwnsPythonObjects &>(py::handle(self_base));
for (auto &item : self.list) {
diff --git a/docs/advanced/deprecated.rst b/docs/advanced/deprecated.rst
index dc07a77..c9f4a2e 100644
--- a/docs/advanced/deprecated.rst
+++ b/docs/advanced/deprecated.rst
@@ -3,8 +3,6 @@
Deprecated
##########
-Support for Python 3.8 is deprecated and will be removed in 3.1.
-
Support for C++11 is deprecated and will be removed in a future version. Please
use at least C++14.
diff --git a/docs/basics.rst b/docs/basics.rst
index 074d988..7f77f20 100644
--- a/docs/basics.rst
+++ b/docs/basics.rst
@@ -32,15 +32,14 @@
Windows
-------
-On Windows, only **Visual Studio 2017** and newer are supported.
+On Windows, only **Visual Studio 2019** and newer are supported.
.. Note::
- To use the C++17 in Visual Studio 2017 (MSVC 14.1), pybind11 requires the flag
- ``/permissive-`` to be passed to the compiler `to enforce standard conformance`_. When
- building with Visual Studio 2019, this is not strictly necessary, but still advised.
+ The ``/permissive-`` flag `to enforce standard conformance`_ is not necessary, but it is
+ still advised.
-.. _`to enforce standard conformance`: https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=vs-2017
+.. _`to enforce standard conformance`: https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance
To compile and run the tests:
diff --git a/docs/compiling.rst b/docs/compiling.rst
index 1838777..a6bee86 100644
--- a/docs/compiling.rst
+++ b/docs/compiling.rst
@@ -429,7 +429,7 @@
.. code-block:: bash
- cmake -DPYBIND11_PYTHON_VERSION=3.8 ..
+ cmake -DPYBIND11_PYTHON_VERSION=3.9 ..
# Another method:
cmake -DPYTHON_EXECUTABLE=/path/to/python ..
@@ -495,7 +495,7 @@
cmake_minimum_required(VERSION 3.15...4.2)
project(example LANGUAGES CXX)
- find_package(Python 3.8 COMPONENTS Interpreter Development REQUIRED)
+ find_package(Python 3.9 COMPONENTS Interpreter Development REQUIRED)
find_package(pybind11 CONFIG REQUIRED)
# or add_subdirectory(pybind11)
diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h
index 9ab6e33..1d857a0 100644
--- a/include/pybind11/cast.h
+++ b/include/pybind11/cast.h
@@ -2262,13 +2262,8 @@
if (m_names) {
nargs -= m_names.size();
}
- PyObject *result =
-#if PY_VERSION_HEX >= 0x03090000
- PyObject_Vectorcall(
-#else
- _PyObject_Vectorcall(
-#endif
- ptr, m_args.data() + 1, nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, m_names.ptr());
+ PyObject *result = PyObject_Vectorcall(
+ ptr, m_args.data() + 1, nargs | PY_VECTORCALL_ARGUMENTS_OFFSET, m_names.ptr());
if (!result) {
throw error_already_set();
}
diff --git a/include/pybind11/detail/class.h b/include/pybind11/detail/class.h
index 8b9d0b8..06a761d 100644
--- a/include/pybind11/detail/class.h
+++ b/include/pybind11/detail/class.h
@@ -586,10 +586,8 @@
PyObject *&dict = *_PyObject_GetDictPtr(self);
Py_VISIT(dict);
#endif
-// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
-#if PY_VERSION_HEX >= 0x03090000
+ // https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
Py_VISIT(Py_TYPE(self));
-#endif
return 0;
}
diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h
index e22763c..7f182af 100644
--- a/include/pybind11/detail/common.h
+++ b/include/pybind11/detail/common.h
@@ -10,8 +10,8 @@
#pragma once
#include <pybind11/conduit/wrap_include_python_h.h>
-#if PY_VERSION_HEX < 0x03080000
-# error "PYTHON < 3.8 IS UNSUPPORTED. pybind11 v2.13 was the last to support Python 3.7."
+#if PY_VERSION_HEX < 0x03090000
+# error "PYTHON < 3.9 IS UNSUPPORTED. pybind11 v3.0 was the last to support Python 3.8."
#endif
// Similar to Python's convention: https://docs.python.org/3/c-api/apiabiversion.html
@@ -87,7 +87,7 @@
# endif
#endif
-#if defined(__cpp_lib_launder) && !(defined(_MSC_VER) && (_MSC_VER < 1920)) // See PR #5968
+#if defined(__cpp_lib_launder)
# define PYBIND11_STD_LAUNDER std::launder
# define PYBIND11_HAS_STD_LAUNDER 1
#else
@@ -132,8 +132,8 @@
# error pybind11 requires gcc 4.8 or newer
# endif
#elif defined(_MSC_VER)
-# if _MSC_VER < 1910
-# error pybind11 2.10+ requires MSVC 2017 or newer
+# if _MSC_VER < 1920
+# error pybind11 3.1+ requires MSVC 2019 or newer
# endif
#endif
@@ -826,7 +826,7 @@
#endif
/// Compile-time all/any/none of that check the boolean value of all template types
-#if defined(__cpp_fold_expressions) && !(defined(_MSC_VER) && (_MSC_VER < 1916))
+#if defined(__cpp_fold_expressions)
template <class... Ts>
using all_of = bool_constant<(Ts::value && ...)>;
template <class... Ts>
@@ -1357,7 +1357,7 @@
// Use at your own risk!
// See also https://en.cppreference.com/w/cpp/memory/enable_shared_from_this, and in particular
// the `std::shared_ptr<Good> gp1 = not_so_good.getptr();` and `try`-`catch` parts of the example.
-#if defined(__cpp_lib_enable_shared_from_this) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
+#if defined(__cpp_lib_enable_shared_from_this)
return holder_value_ptr->weak_from_this().lock();
#else
try {
@@ -1370,19 +1370,10 @@
// For silencing "unused" compiler warnings in special situations.
template <typename... Args>
-#if defined(_MSC_VER) && _MSC_VER < 1920 // MSVC 2017
-constexpr
-#endif
- inline void silence_unused_warnings(Args &&...) {
-}
+inline void silence_unused_warnings(Args &&...) {}
-// MSVC warning C4100: Unreferenced formal parameter
-#if defined(_MSC_VER) && _MSC_VER <= 1916
-# define PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(...) \
- detail::silence_unused_warnings(__VA_ARGS__)
-#else
-# define PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(...)
-#endif
+// MSVC warning C4100: Unreferenced formal parameter (only incorrect before MSVC 2019)
+#define PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(...)
// GCC -Wunused-but-set-parameter All GCC versions (as of July 2021).
#if defined(__GNUG__) && !defined(__clang__) && !defined(__INTEL_COMPILER)
diff --git a/include/pybind11/detail/function_record_pyobject.h b/include/pybind11/detail/function_record_pyobject.h
index 94d27ad..42b0e96 100644
--- a/include/pybind11/detail/function_record_pyobject.h
+++ b/include/pybind11/detail/function_record_pyobject.h
@@ -48,8 +48,8 @@
// Python 3.12+ emits a DeprecationWarning for heap types whose tp_name does
// not contain a dot ('.') and that lack a __module__ attribute. For pybind11's
// internal function_record type, we do not have an actual module object to
-// attach, so we cannot use PyType_FromModuleAndSpec (introduced in Python 3.9)
-// to set __module__ automatically.
+// attach, so we cannot use PyType_FromModuleAndSpec to set __module__
+// automatically.
//
// As a workaround, we define a "qualified" type name that includes a dummy
// module name (PYBIND11_DUMMY_MODULE_NAME). This is nonβidiomatic but avoids
@@ -59,8 +59,7 @@
//
// even though no real pybind11_builtins module exists. If pybind11 gains an
// actual module object in the future, this code should switch to
-// PyType_FromModuleAndSpec for Python 3.9+ and drop the dummy module
-// workaround.
+// PyType_FromModuleAndSpec and drop the dummy module workaround.
//
// Note that this name is versioned.
#define PYBIND11_DETAIL_FUNCTION_RECORD_TP_PLAINNAME \
diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h
index b6d03ca..161b988 100644
--- a/include/pybind11/detail/type_caster_base.h
+++ b/include/pybind11/detail/type_caster_base.h
@@ -1144,7 +1144,7 @@
if (type->operator_new) {
vptr = type->operator_new(type->type_size);
} else {
-#if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
+#if defined(__cpp_aligned_new)
if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
vptr = ::operator new(type->type_size, std::align_val_t(type->type_align));
} else {
diff --git a/include/pybind11/embed.h b/include/pybind11/embed.h
index c05887c..078f419 100644
--- a/include/pybind11/embed.h
+++ b/include/pybind11/embed.h
@@ -12,9 +12,6 @@
#include "pybind11.h"
#include "eval.h"
-#include <memory>
-#include <vector>
-
#if defined(PYPY_VERSION)
# error Embedding the interpreter is not supported with PyPy
#endif
@@ -82,60 +79,14 @@
}
};
-struct wide_char_arg_deleter {
- void operator()(wchar_t *ptr) const {
- // API docs: https://docs.python.org/3/c-api/sys.html#c.Py_DecodeLocale
- PyMem_RawFree(ptr);
- }
-};
-
-inline wchar_t *widen_chars(const char *safe_arg) {
- wchar_t *widened_arg = Py_DecodeLocale(safe_arg, nullptr);
- return widened_arg;
-}
-
inline void precheck_interpreter() {
if (Py_IsInitialized() != 0) {
pybind11_fail("The interpreter is already running");
}
}
-#if !defined(PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX)
-# define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
-#endif
-
-#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
-inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
- int argc,
- const char *const *argv,
- bool add_program_dir_to_path) {
- detail::precheck_interpreter();
- Py_InitializeEx(init_signal_handlers ? 1 : 0);
-
- auto argv_size = static_cast<size_t>(argc);
- // SetArgv* on python 3 takes wchar_t, so we have to convert.
- std::unique_ptr<wchar_t *[]> widened_argv(new wchar_t *[argv_size]);
- std::vector<std::unique_ptr<wchar_t[], detail::wide_char_arg_deleter>> widened_argv_entries;
- widened_argv_entries.reserve(argv_size);
- for (size_t ii = 0; ii < argv_size; ++ii) {
- widened_argv_entries.emplace_back(detail::widen_chars(argv[ii]));
- if (!widened_argv_entries.back()) {
- // A null here indicates a character-encoding failure or the python
- // interpreter out of memory. Give up.
- return;
- }
- widened_argv[ii] = widened_argv_entries.back().get();
- }
-
- auto *pysys_argv = widened_argv.get();
-
- PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
-}
-#endif
-
PYBIND11_NAMESPACE_END(detail)
-#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
inline void initialize_interpreter(PyConfig *config,
int argc = 0,
const char *const *argv = nullptr,
@@ -163,35 +114,27 @@
}
PyConfig_Clear(config);
}
-#endif
/** \rst
Initialize the Python interpreter. No other pybind11 or CPython API functions can be
called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The
optional `init_signal_handlers` parameter can be used to skip the registration of
- signal handlers (see the `Python documentation`_ for details). Calling this function
- again after the interpreter has already been initialized is a fatal error.
+ signal handlers. Calling this function again while an interpreter is running throws
+ ``std::runtime_error``.
- If initializing the Python interpreter fails, then the program is terminated. (This
- is controlled by the CPython runtime and is an exception to pybind11's normal behavior
- of throwing exceptions on errors.)
+ The interpreter starts from a ``PyConfig``, with ``PyConfig_SetBytesArgv`` and
+ ``Py_InitializeFromConfig``. If the start fails, this function throws
+ ``std::runtime_error``. See the `Python documentation`_ for these functions.
The remaining optional parameters, `argc`, `argv`, and `add_program_dir_to_path` are
used to populate ``sys.argv`` and ``sys.path``.
- See the |PySys_SetArgvEx documentation|_ for details.
- .. _Python documentation: https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx
- .. |PySys_SetArgvEx documentation| replace:: ``PySys_SetArgvEx`` documentation
- .. _PySys_SetArgvEx documentation: https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
+ .. _Python documentation: https://docs.python.org/3/c-api/init_config.html
\endrst */
inline void initialize_interpreter(bool init_signal_handlers = true,
int argc = 0,
const char *const *argv = nullptr,
bool add_program_dir_to_path = true) {
-#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
- detail::initialize_interpreter_pre_pyconfig(
- init_signal_handlers, argc, argv, add_program_dir_to_path);
-#else
PyConfig config;
PyConfig_InitPythonConfig(&config);
// See PR #4473 for background
@@ -199,7 +142,6 @@
config.install_signal_handlers = init_signal_handlers ? 1 : 0;
initialize_interpreter(&config, argc, argv, add_program_dir_to_path);
-#endif
// There is exactly one interpreter alive currently.
detail::has_seen_non_main_interpreter() = false;
@@ -293,14 +235,12 @@
initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path);
}
-#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
explicit scoped_interpreter(PyConfig *config,
int argc = 0,
const char *const *argv = nullptr,
bool add_program_dir_to_path = true) {
initialize_interpreter(config, argc, argv, add_program_dir_to_path);
}
-#endif
scoped_interpreter(const scoped_interpreter &) = delete;
scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; }
diff --git a/include/pybind11/functional.h b/include/pybind11/functional.h
index c712279..c06fabe 100644
--- a/include/pybind11/functional.h
+++ b/include/pybind11/functional.h
@@ -20,13 +20,7 @@
// ensure GIL is held during functor destruction
struct func_handle {
function f;
-#if !(defined(_MSC_VER) && _MSC_VER == 1916 && defined(PYBIND11_CPP17))
- // This triggers a syntax error under very special conditions (very weird indeed).
- explicit
-#endif
- func_handle(function &&f_) noexcept
- : f(std::move(f_)) {
- }
+ explicit func_handle(function &&f_) noexcept : f(std::move(f_)) {}
func_handle(const func_handle &f_) { operator=(f_); }
func_handle &operator=(const func_handle &f_) {
gil_scoped_acquire acq;
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index e41076d..12559dd 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -1968,7 +1968,7 @@
inline void call_operator_delete(void *p, size_t s, size_t a) {
(void) s;
(void) a;
-#if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
+#if defined(__cpp_aligned_new)
if (a > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
# ifdef __cpp_sized_deallocation
::operator delete(p, s, std::align_val_t(a));
@@ -3847,24 +3847,23 @@
/* Don't call dispatch code if invoked from overridden function.
Unfortunately this doesn't work on PyPy and GraalPy. */
#if !defined(PYPY_VERSION) && !defined(GRAALVM_PYTHON)
-# if PY_VERSION_HEX >= 0x03090000
PyFrameObject *frame = PyThreadState_GetFrame(PyThreadState_Get());
if (frame != nullptr) {
PyCodeObject *f_code = PyFrame_GetCode(frame);
// f_code is guaranteed to not be NULL
if (std::string(str(f_code->co_name)) == name && f_code->co_argcount > 0) {
-# if PY_VERSION_HEX >= 0x030d0000
+# if PY_VERSION_HEX >= 0x030d0000
PyObject *locals = PyEval_GetFrameLocals();
-# else
+# else
PyObject *locals = PyEval_GetLocals();
Py_XINCREF(locals);
-# endif
+# endif
if (locals != nullptr) {
-# if PY_VERSION_HEX >= 0x030b0000
+# if PY_VERSION_HEX >= 0x030b0000
PyObject *co_varnames = PyCode_GetVarnames(f_code);
-# else
+# else
PyObject *co_varnames = PyObject_GetAttrString((PyObject *) f_code, "co_varnames");
-# endif
+# endif
PyObject *self_arg = PyTuple_GET_ITEM(co_varnames, 0);
Py_DECREF(co_varnames);
PyObject *self_caller = dict_getitem(locals, self_arg);
@@ -3879,18 +3878,6 @@
Py_DECREF(f_code);
Py_DECREF(frame);
}
-# else
- PyFrameObject *frame = PyThreadState_Get()->frame;
- if (frame != nullptr && (std::string) str(frame->f_code->co_name) == name
- && frame->f_code->co_argcount > 0) {
- PyFrame_FastToLocals(frame);
- PyObject *self_caller
- = dict_getitem(frame->f_locals, PyTuple_GET_ITEM(frame->f_code->co_varnames, 0));
- if (self_caller == self.ptr()) {
- return function();
- }
- }
-# endif
#else
/* PyPy currently doesn't provide a detailed cpyext emulation of
diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h
index ff4be6a..13a6eba 100644
--- a/include/pybind11/pytypes.h
+++ b/include/pybind11/pytypes.h
@@ -670,12 +670,7 @@
Py_XINCREF(frame);
result += "\n\nAt:\n";
while (frame) {
-# if PY_VERSION_HEX >= 0x030900B1
PyCodeObject *f_code = PyFrame_GetCode(frame);
-# else
- PyCodeObject *f_code = frame->f_code;
- Py_INCREF(f_code);
-# endif
int lineno = PyFrame_GetLineNumber(frame);
result += " ";
result += handle(f_code->co_filename).cast<std::string>();
@@ -685,12 +680,7 @@
result += handle(f_code->co_name).cast<std::string>();
result += '\n';
Py_DECREF(f_code);
-# if PY_VERSION_HEX >= 0x030900B1
auto *b_frame = PyFrame_GetBack(frame);
-# else
- auto *b_frame = frame->f_back;
- Py_XINCREF(b_frame);
-# endif
Py_DECREF(frame);
frame = b_frame;
}
diff --git a/pybind11/__init__.py b/pybind11/__init__.py
index e9d033c..df5e8ee 100644
--- a/pybind11/__init__.py
+++ b/pybind11/__init__.py
@@ -2,8 +2,8 @@
import sys
-if sys.version_info < (3, 8): # noqa: UP036
- msg = "pybind11 does not support Python < 3.8. v2.13 was the last release supporting Python 3.7."
+if sys.version_info < (3, 9): # noqa: UP036
+ msg = "pybind11 does not support Python < 3.9. v3.0 was the last release supporting Python 3.8."
raise ImportError(msg)
diff --git a/pybind11/setup_helpers.py b/pybind11/setup_helpers.py
index 300688b..8f42605 100644
--- a/pybind11/setup_helpers.py
+++ b/pybind11/setup_helpers.py
@@ -48,16 +48,13 @@
import tempfile
import threading
import warnings
+from collections.abc import Iterable, Iterator
from functools import lru_cache
from pathlib import Path
from typing import (
Any,
Callable,
- Iterable,
- Iterator,
- List,
Optional,
- Tuple,
TypeVar,
Union,
)
@@ -175,8 +172,7 @@
"You cannot safely change the cxx_level after setting it!", stacklevel=2
)
- # MSVC 2015 Update 3 and later only have 14 (and later 17) modes, so
- # force a valid flag here.
+ # MSVC only has 14 and later modes, so force a valid flag here.
if WIN and level == 11:
level = 14
@@ -347,16 +343,16 @@
CCompilerMethod = Callable[
[
distutils.ccompiler.CCompiler,
- List[str],
+ list[str],
Optional[str],
- Optional[List[Union[Tuple[str], Tuple[str, Optional[str]]]]],
- Optional[List[str]],
+ Optional[list[Union[tuple[str], tuple[str, Optional[str]]]]],
+ Optional[list[str]],
bool,
- Optional[List[str]],
- Optional[List[str]],
- Optional[List[str]],
+ Optional[list[str]],
+ Optional[list[str]],
+ Optional[list[str]],
],
- List[str],
+ list[str],
]
diff --git a/pyproject.toml b/pyproject.toml
index c3395aa..caf0a8b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,7 +16,6 @@
"Topic :: Utilities",
"Programming Language :: C++",
"Programming Language :: Python :: 3 :: Only",
- "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
@@ -34,7 +33,7 @@
"Python bindings",
]
dynamic = ["version", "optional-dependencies"]
-requires-python = ">=3.8"
+requires-python = ">=3.9"
[project.urls]
Homepage = "https://github.com/pybind/pybind11"
@@ -120,7 +119,7 @@
[tool.mypy]
files = ["pybind11"]
-python_version = "3.8"
+python_version = "3.9"
strict = true
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
warn_unreachable = true
@@ -131,7 +130,7 @@
[tool.pylint]
-master.py-version = "3.8"
+master.py-version = "3.9"
reports.output-format = "colorized"
messages_control.disable = [
"design",
diff --git a/tests/extra_python_package/test_files.py b/tests/extra_python_package/test_files.py
index 0abb48c..e2c1856 100644
--- a/tests/extra_python_package/test_files.py
+++ b/tests/extra_python_package/test_files.py
@@ -10,8 +10,8 @@
import sysconfig
import tarfile
import zipfile
+from collections.abc import Generator
from pathlib import Path
-from typing import Generator
import pytest
diff --git a/tests/requirements.txt b/tests/requirements.txt
index 1ba4026..e10fb40 100644
--- a/tests/requirements.txt
+++ b/tests/requirements.txt
@@ -3,11 +3,10 @@
build>=1
# No released numpy has cp315 wheels yet; drop the upper bound once it does.
numpy>=2.4.0; platform_python_implementation=="CPython" and python_version>="3.14" and python_version<"3.15"
-numpy~=1.23.0; python_version=="3.8" and platform_python_implementation=="PyPy"
numpy~=1.25.0; python_version=="3.9" and platform_python_implementation=="PyPy"
numpy~=2.2.0; python_version=="3.10" and platform_python_implementation=="PyPy"
numpy~=2.2.0; platform_python_implementation=="GraalVM" and sys_platform=="linux"
-numpy~=1.21.5; platform_python_implementation=="CPython" and python_version>="3.8" and python_version<"3.10"
+numpy~=1.21.5; platform_python_implementation=="CPython" and python_version=="3.9"
numpy~=1.22.2; platform_python_implementation=="CPython" and python_version=="3.10"
numpy~=1.26.0; platform_python_implementation=="CPython" and python_version>="3.11" and python_version<"3.13" and platform_machine!="ARM64"
numpy>=2.3.0; platform_python_implementation=="CPython" and python_version>="3.11" and platform_machine=="ARM64"
diff --git a/tests/test_builtin_casters.py b/tests/test_builtin_casters.py
index ee73339..a08ac41 100644
--- a/tests/test_builtin_casters.py
+++ b/tests/test_builtin_casters.py
@@ -302,7 +302,6 @@
assert noconvert(7) == 7
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 sys.version_info < (3, 10) and env.CPYTHON:
with pytest.deprecated_call():
assert convert(Int()) == 42
@@ -312,8 +311,6 @@
cant_convert(NotInt())
cant_convert(Float())
- # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
- # but pybind11 "backports" this behavior.
assert convert(Index()) == 42
assert isinstance(convert(Index()), int)
assert noconvert(Index()) == 42
@@ -419,9 +416,8 @@
# The implicit conversion from np.float32 is undesirable but currently accepted.
# 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) <= sys.version_info < (3, 10) and env.CPYTHON:
+ if sys.version_info < (3, 10) and env.CPYTHON:
with pytest.deprecated_call():
assert convert(np.float32(3.14159)) == 3
else:
diff --git a/tests/test_custom_type_setup.cpp b/tests/test_custom_type_setup.cpp
index 15516b2..5235729 100644
--- a/tests/test_custom_type_setup.cpp
+++ b/tests/test_custom_type_setup.cpp
@@ -71,10 +71,8 @@
auto *type = &heap_type->ht_type;
type->tp_flags |= Py_TPFLAGS_HAVE_GC;
type->tp_traverse = [](PyObject *self_base, visitproc visit, void *arg) {
-// https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
-#if PY_VERSION_HEX >= 0x03090000
+ // https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_traverse
Py_VISIT(Py_TYPE(self_base));
-#endif
if (py::detail::is_holder_constructed(self_base)) {
auto &self = py::cast<ContainerOwnsPythonObjects &>(py::handle(self_base));
for (auto &item : self.list) {
diff --git a/tests/test_docs_advanced_cast_custom.py b/tests/test_docs_advanced_cast_custom.py
index 5374cbc..63d608c 100644
--- a/tests/test_docs_advanced_cast_custom.py
+++ b/tests/test_docs_advanced_cast_custom.py
@@ -1,6 +1,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Sequence
+from collections.abc import Sequence
+from typing import TYPE_CHECKING
if TYPE_CHECKING:
from conftest import SanitizedString
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index 1ee13ba..c52a295 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -94,14 +94,16 @@
def ignore_pytest_unraisable_warning(f):
unraisable = "PytestUnraisableExceptionWarning"
- if hasattr(pytest, unraisable): # Python >= 3.8 and pytest >= 6
+ if hasattr(pytest, unraisable): # pytest >= 6
dec = pytest.mark.filterwarnings(f"ignore::pytest.{unraisable}")
return dec(f)
return f
# TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583
-@pytest.mark.xfail(env.PYPY, reason="Failure on PyPy 3.8 (7.3.7)", strict=False)
+@pytest.mark.xfail(
+ env.PYPY, reason="Failure on PyPy (still fails with 7.3.23)", strict=False
+)
@ignore_pytest_unraisable_warning
def test_python_alreadyset_in_destructor(monkeypatch, capsys):
triggered = False
diff --git a/tests/test_multiple_interpreters.py b/tests/test_multiple_interpreters.py
index 65b2733..6ca4fd8 100644
--- a/tests/test_multiple_interpreters.py
+++ b/tests/test_multiple_interpreters.py
@@ -157,9 +157,10 @@
"""
).strip()
- with contextlib.closing(interpreters.create()) as interp1, contextlib.closing(
- interpreters.create()
- ) as interp2:
+ with (
+ contextlib.closing(interpreters.create()) as interp1,
+ contextlib.closing(interpreters.create()) as interp2,
+ ):
with pytest.raises(
interpreters.ExecutionFailed,
match="does not support loading in subinterpreters",
diff --git a/tests/test_with_catch/test_interpreter.cpp b/tests/test_with_catch/test_interpreter.cpp
index 6010a41..e39f51c 100644
--- a/tests/test_with_catch/test_interpreter.cpp
+++ b/tests/test_with_catch/test_interpreter.cpp
@@ -198,7 +198,6 @@
py::initialize_interpreter();
}
-#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
TEST_CASE("Custom PyConfig") {
py::finalize_interpreter();
PyConfig config;
@@ -261,9 +260,8 @@
}
py::initialize_interpreter();
}
-#endif
-TEST_CASE("Add program dir to path pre-PyConfig") {
+TEST_CASE("Add program dir to path without PyConfig") {
py::finalize_interpreter();
size_t path_size_add_program_dir_to_path_false = 0;
{
@@ -277,7 +275,6 @@
py::initialize_interpreter();
}
-#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
TEST_CASE("Add program dir to path using PyConfig") {
py::finalize_interpreter();
size_t path_size_add_program_dir_to_path_false = 0;
@@ -295,7 +292,6 @@
}
py::initialize_interpreter();
}
-#endif
TEST_CASE("Restart the interpreter") {
// Verify pre-restart state.
diff --git a/tools/FindPythonLibsNew.cmake b/tools/FindPythonLibsNew.cmake
index 7351bca..d72e213 100644
--- a/tools/FindPythonLibsNew.cmake
+++ b/tools/FindPythonLibsNew.cmake
@@ -92,7 +92,7 @@
# Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION)
- set(PythonLibsNew_FIND_VERSION "3.8")
+ set(PythonLibsNew_FIND_VERSION "3.9")
endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.27")
diff --git a/tools/pybind11NewTools.cmake b/tools/pybind11NewTools.cmake
index 568b0b0..b0fe207 100644
--- a/tools/pybind11NewTools.cmake
+++ b/tools/pybind11NewTools.cmake
@@ -52,7 +52,7 @@
endif()
find_package(
- Python 3.8 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
+ Python 3.9 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
${_pybind11_quiet} ${_pybind11_global_keyword})
# If we are in submodule mode, export the Python targets to global targets.
@@ -192,8 +192,8 @@
endif()
endif()
-# Python debug libraries expose slightly different objects before 3.8
-# https://docs.python.org/3.6/c-api/intro.html#debugging-builds
+# A debug build of Python needs Py_DEBUG to select the matching ABI.
+# https://docs.python.org/3/c-api/intro.html#debugging-builds
# https://stackoverflow.com/questions/39161202/how-to-work-around-missing-pymodule-create2-in-amd64-win-python35-d-lib
if(PYTHON_IS_DEBUG)
set_property(
diff --git a/tools/pybind11Tools.cmake b/tools/pybind11Tools.cmake
index a51efb3..81faee7 100644
--- a/tools/pybind11Tools.cmake
+++ b/tools/pybind11Tools.cmake
@@ -37,7 +37,7 @@
# A user can set versions manually too
set(Python_ADDITIONAL_VERSIONS
- "3.12;3.11;3.10;3.9;3.8"
+ "3.15;3.14;3.13;3.12;3.11;3.10;3.9"
CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
@@ -100,8 +100,8 @@
"${pybind11_INCLUDE_DIR}" "${PYTHON_INCLUDE_DIRS}"
CACHE INTERNAL "Directories where pybind11 and possibly Python headers are located")
-# Python debug libraries expose slightly different objects before 3.8
-# https://docs.python.org/3.6/c-api/intro.html#debugging-builds
+# A debug build of Python needs Py_DEBUG to select the matching ABI.
+# https://docs.python.org/3/c-api/intro.html#debugging-builds
# https://stackoverflow.com/questions/39161202/how-to-work-around-missing-pymodule-create2-in-amd64-win-python35-d-lib
if(PYTHON_IS_DEBUG)
set_property(