Merge branch 'master' into sh_merge_master

This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-06-21 22:55:00 -07:00
commit d958b789af
84 changed files with 256 additions and 232 deletions

View File

@ -9,7 +9,7 @@ platform:
- x86
environment:
matrix:
- PYTHON: 36
- PYTHON: 38
CONFIG: Debug
install:
- ps: |

View File

@ -33,7 +33,7 @@ jobs:
matrix:
runs-on: [ubuntu-20.04, windows-2022, macos-13]
python:
- '3.6'
- '3.8'
- '3.9'
- '3.12'
- '3.13'
@ -49,16 +49,17 @@ jobs:
include:
# Just add a key
- runs-on: ubuntu-20.04
python: '3.6'
python: '3.8'
args: >
-DPYBIND11_FINDPYTHON=ON
-DCMAKE_CXX_FLAGS="-D_=1"
exercise_D_: 1
- runs-on: ubuntu-20.04
python: 'pypy-3.8'
args: >
-DPYBIND11_FINDPYTHON=ON
- runs-on: windows-2019
python: '3.6'
python: '3.8'
args: >
-DPYBIND11_FINDPYTHON=ON
# Inject a couple Windows 2019 runs
@ -83,7 +84,7 @@ jobs:
- name: Setup Boost (Linux)
# Can't use boost + define _
if: runner.os == 'Linux' && matrix.python != '3.6'
if: runner.os == 'Linux' && matrix.exercise_D_ != 1
run: sudo apt-get install libboost-dev
- name: Setup Boost (macOS)
@ -134,9 +135,7 @@ jobs:
run: cmake --build . --target pytest -j 2
- name: C++11 tests
# TODO: Figure out how to load the DLL on Python 3.8+
if: "!(runner.os == 'Windows' && (matrix.python == 3.8 || matrix.python == 3.9 || matrix.python == '3.10' || matrix.python == '3.11' || matrix.python == 'pypy-3.8'))"
run: cmake --build . --target cpptest -j 2
run: cmake --build . --target cpptest -j 2
- name: Interface test C++11
run: cmake --build . --target test_cmake_build
@ -165,8 +164,6 @@ jobs:
run: cmake --build build2 --target pytest
- name: C++ tests
# TODO: Figure out how to load the DLL on Python 3.8+
if: "!(runner.os == 'Windows' && (matrix.python == 3.8 || matrix.python == 3.9 || matrix.python == '3.10' || matrix.python == '3.11' || matrix.python == 'pypy-3.8'))"
run: cmake --build build2 --target cpptest
# Third build - C++17 mode with unstable ABI
@ -660,15 +657,13 @@ jobs:
cmake --build build-17 --target test_cmake_build
# Testing on CentOS (manylinux uses a centos base, and this is an easy way
# to get GCC 4.8, which is the manylinux1 compiler).
# Testing on CentOS (manylinux uses a centos base).
centos:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
container:
- "centos:7" # GCC 4.8
- "almalinux:8"
- "almalinux:9"
@ -678,18 +673,13 @@ jobs:
steps:
- name: Latest actions/checkout
uses: actions/checkout@v4
if: matrix.container != 'centos:7'
- name: Pin actions/checkout as required for centos:7
uses: actions/checkout@v3
if: matrix.container == 'centos:7'
- name: Add Python 3.8
if: matrix.container == 'almalinux:8'
run: dnf update -y && dnf install -y python38-devel gcc-c++ make git
- name: Add Python 3 (RHEL 7)
if: matrix.container == 'centos:7'
run: yum update -y && yum install -y python3-devel gcc-c++ make git
- name: Add Python 3 (RHEL 8+)
if: matrix.container != 'centos:7'
- name: Add Python 3 (default)
if: matrix.container != 'almalinux:8'
run: dnf update -y && dnf install -y python3-devel gcc-c++ make git
- name: Update pip
@ -812,17 +802,25 @@ jobs:
fail-fast: false
matrix:
python:
- 3.6
- 3.7
- 3.8
- 3.9
- '3.7'
- '3.8'
- '3.9'
- '3.10'
- '3.11'
- '3.12'
include:
- python: 3.9
- python: '3.12'
args: -DCMAKE_CXX_STANDARD=20
- python: 3.8
- python: '3.11'
args: -DCMAKE_CXX_STANDARD=20
- python: '3.10'
args: -DCMAKE_CXX_STANDARD=20
- python: '3.9'
args: -DCMAKE_CXX_STANDARD=20
- python: '3.8'
args: -DCMAKE_CXX_STANDARD=17
- python: 3.7
- python: '3.7'
args: -DCMAKE_CXX_STANDARD=14

View File

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

View File

@ -38,7 +38,7 @@ dependency.
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 (3.6+, or PyPy) and the C++
lines of code and depend on Python (3.7+, or PyPy) 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
@ -83,7 +83,7 @@ Goodies
In addition to the core functionality, pybind11 provides some extra
goodies:
- Python 3.6+, and PyPy3 7.3 are supported with an implementation-agnostic
- Python 3.7+, and PyPy3 7.3 are supported with an implementation-agnostic
interface (pybind11 2.9 was the last version to support Python 2 and 3.5).
- It is possible to bind C++11 lambda functions with captured

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import datetime as dt
import os
import random

View File

@ -426,7 +426,7 @@ with ``PYTHON_EXECUTABLE``. For example:
.. code-block:: bash
cmake -DPYBIND11_PYTHON_VERSION=3.6 ..
cmake -DPYBIND11_PYTHON_VERSION=3.7 ..
# Another method:
cmake -DPYTHON_EXECUTABLE=/path/to/python ..
@ -493,7 +493,7 @@ existing targets instead:
cmake_minimum_required(VERSION 3.15...3.22)
project(example LANGUAGES CXX)
find_package(Python 3.6 COMPONENTS Interpreter Development REQUIRED)
find_package(Python 3.7 COMPONENTS Interpreter Development REQUIRED)
find_package(pybind11 CONFIG REQUIRED)
# or add_subdirectory(pybind11)

View File

@ -11,6 +11,7 @@
#
# All configuration values have a default; values that are commented out
# serve to show the default.
from __future__ import annotations
import os
import re

View File

@ -569,17 +569,9 @@ inline void enable_dynamic_attributes(PyHeapTypeObject *heap_type) {
type->tp_traverse = pybind11_traverse;
type->tp_clear = pybind11_clear;
static PyGetSetDef getset[] = {{
#if PY_VERSION_HEX < 0x03070000
const_cast<char *>("__dict__"),
#else
"__dict__",
#endif
PyObject_GenericGetDict,
PyObject_GenericSetDict,
nullptr,
nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr}};
static PyGetSetDef getset[]
= {{"__dict__", PyObject_GenericGetDict, PyObject_GenericSetDict, nullptr, nullptr},
{nullptr, nullptr, nullptr, nullptr, nullptr}};
type->tp_getset = getset;
}

View File

@ -272,9 +272,8 @@ PYBIND11_WARNING_DISABLE_MSVC(4505)
#endif
#include <Python.h>
// Reminder: WITH_THREAD is always defined if PY_VERSION_HEX >= 0x03070000
#if PY_VERSION_HEX < 0x03060000
# error "PYTHON < 3.6 IS UNSUPPORTED. pybind11 v2.9 was the last to support Python 2 and 3.5."
#if PY_VERSION_HEX < 0x03070000
# error "PYTHON < 3.7 IS UNSUPPORTED. pybind11 v2.12 was the last to support Python 3.6."
#endif
#include <frameobject.h>
#include <pythread.h>

View File

@ -11,7 +11,7 @@
#include "common.h"
#if defined(WITH_THREAD) && defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
# include "../gil.h"
#endif
@ -65,65 +65,41 @@ inline PyObject *make_object_base_type(PyTypeObject *metaclass);
// The old Python Thread Local Storage (TLS) API is deprecated in Python 3.7 in favor of the new
// Thread Specific Storage (TSS) API.
#if PY_VERSION_HEX >= 0x03070000
// Avoid unnecessary allocation of `Py_tss_t`, since we cannot use
// `Py_LIMITED_API` anyway.
# if PYBIND11_INTERNALS_VERSION > 4
# define PYBIND11_TLS_KEY_REF Py_tss_t &
# if defined(__clang__)
# define PYBIND11_TLS_KEY_INIT(var) \
_Pragma("clang diagnostic push") /**/ \
_Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
Py_tss_t var \
= Py_tss_NEEDS_INIT; \
_Pragma("clang diagnostic pop")
# elif defined(__GNUC__) && !defined(__INTEL_COMPILER)
# define PYBIND11_TLS_KEY_INIT(var) \
_Pragma("GCC diagnostic push") /**/ \
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
Py_tss_t var \
= Py_tss_NEEDS_INIT; \
_Pragma("GCC diagnostic pop")
# else
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT;
# endif
# define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0)
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key))
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value))
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr)
# define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key))
#if PYBIND11_INTERNALS_VERSION > 4
# define PYBIND11_TLS_KEY_REF Py_tss_t &
# if defined(__clang__)
# define PYBIND11_TLS_KEY_INIT(var) \
_Pragma("clang diagnostic push") /**/ \
_Pragma("clang diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
Py_tss_t var \
= Py_tss_NEEDS_INIT; \
_Pragma("clang diagnostic pop")
# elif defined(__GNUC__) && !defined(__INTEL_COMPILER)
# define PYBIND11_TLS_KEY_INIT(var) \
_Pragma("GCC diagnostic push") /**/ \
_Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"") /**/ \
Py_tss_t var \
= Py_tss_NEEDS_INIT; \
_Pragma("GCC diagnostic pop")
# else
# define PYBIND11_TLS_KEY_REF Py_tss_t *
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr;
# define PYBIND11_TLS_KEY_CREATE(var) \
(((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0))
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value))
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key)
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t var = Py_tss_NEEDS_INIT;
# endif
# define PYBIND11_TLS_KEY_CREATE(var) (PyThread_tss_create(&(var)) == 0)
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get(&(key))
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set(&(key), (value))
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set(&(key), nullptr)
# define PYBIND11_TLS_FREE(key) PyThread_tss_delete(&(key))
#else
// Usually an int but a long on Cygwin64 with Python 3.x
# define PYBIND11_TLS_KEY_REF decltype(PyThread_create_key())
# 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 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.
inline void tls_replace_value(PYBIND11_TLS_KEY_REF key, void *value) {
PyThread_delete_key_value(key);
PyThread_set_key_value(key, value);
}
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_delete_key_value(key)
# define PYBIND11_TLS_REPLACE_VALUE(key, value) \
::pybind11::detail::tls_replace_value((key), (value))
# else
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_set_key_value((key), nullptr)
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_set_key_value((key), (value))
# endif
# define PYBIND11_TLS_FREE(key) (void) key
# define PYBIND11_TLS_KEY_REF Py_tss_t *
# define PYBIND11_TLS_KEY_INIT(var) Py_tss_t *var = nullptr;
# define PYBIND11_TLS_KEY_CREATE(var) \
(((var) = PyThread_tss_alloc()) != nullptr && (PyThread_tss_create((var)) == 0))
# define PYBIND11_TLS_GET_VALUE(key) PyThread_tss_get((key))
# define PYBIND11_TLS_REPLACE_VALUE(key, value) PyThread_tss_set((key), (value))
# define PYBIND11_TLS_DELETE_VALUE(key) PyThread_tss_set((key), nullptr)
# define PYBIND11_TLS_FREE(key) PyThread_tss_free(key)
#endif
// Python loads modules by default with dlopen with the RTLD_LOCAL flag; under libc++ and possibly
@ -217,28 +193,27 @@ struct internals {
PyTypeObject *static_property_type;
PyTypeObject *default_metaclass;
PyObject *instance_base;
#if defined(WITH_THREAD)
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
PYBIND11_TLS_KEY_INIT(tstate)
# if PYBIND11_INTERNALS_VERSION > 4
#if PYBIND11_INTERNALS_VERSION > 4
PYBIND11_TLS_KEY_INIT(loader_life_support_tls_key)
# endif // PYBIND11_INTERNALS_VERSION > 4
#endif // PYBIND11_INTERNALS_VERSION > 4
// Unused if PYBIND11_SIMPLE_GIL_MANAGEMENT is defined:
PyInterpreterState *istate = nullptr;
# if PYBIND11_INTERNALS_VERSION > 4
#if PYBIND11_INTERNALS_VERSION > 4
// Note that we have to use a std::string to allocate memory to ensure a unique address
// We want unique addresses since we use pointer equality to compare function records
std::string function_record_capsule_name = internals_function_record_capsule_name;
# endif
#endif
internals() = default;
internals(const internals &other) = delete;
internals &operator=(const internals &other) = delete;
~internals() {
# if PYBIND11_INTERNALS_VERSION > 4
#if PYBIND11_INTERNALS_VERSION > 4
PYBIND11_TLS_FREE(loader_life_support_tls_key);
# endif // PYBIND11_INTERNALS_VERSION > 4
#endif // PYBIND11_INTERNALS_VERSION > 4
// This destructor is called *after* Py_Finalize() in finalize_interpreter().
// That *SHOULD BE* fine. The following details what happens when PyThread_tss_free is
@ -249,7 +224,6 @@ struct internals {
// that the `tstate` be allocated with the CPython allocator.
PYBIND11_TLS_FREE(tstate);
}
#endif
};
/// Additional type information which does not fit into the PyTypeObject.
@ -334,11 +308,7 @@ struct type_info {
#endif
#ifndef PYBIND11_INTERNALS_KIND
# if defined(WITH_THREAD)
# define PYBIND11_INTERNALS_KIND ""
# else
# define PYBIND11_INTERNALS_KIND "_without_thread"
# endif
# define PYBIND11_INTERNALS_KIND ""
#endif
/// See README_smart_holder.rst:
@ -531,10 +501,9 @@ PYBIND11_NOINLINE internals &get_internals() {
return **internals_pp;
}
#if defined(WITH_THREAD)
# if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
#if defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
gil_scoped_acquire gil;
# else
#else
// Ensure that the GIL is held since we will need to make Python calls.
// Cannot use py::gil_scoped_acquire here since that constructor calls get_internals.
struct gil_scoped_acquire_local {
@ -544,7 +513,6 @@ PYBIND11_NOINLINE internals &get_internals() {
~gil_scoped_acquire_local() { PyGILState_Release(state); }
const PyGILState_STATE state;
} gil;
# endif
#endif
error_scope err_scope;
@ -569,7 +537,6 @@ PYBIND11_NOINLINE internals &get_internals() {
}
auto *&internals_ptr = *internals_pp;
internals_ptr = new internals();
#if defined(WITH_THREAD)
PyThreadState *tstate = PyThreadState_Get();
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
@ -578,15 +545,14 @@ PYBIND11_NOINLINE internals &get_internals() {
}
PYBIND11_TLS_REPLACE_VALUE(internals_ptr->tstate, tstate);
# if PYBIND11_INTERNALS_VERSION > 4
#if PYBIND11_INTERNALS_VERSION > 4
// NOLINTNEXTLINE(bugprone-assignment-in-if-condition)
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->loader_life_support_tls_key)) {
pybind11_fail("get_internals: could not successfully initialize the "
"loader_life_support TSS key!");
}
# endif
internals_ptr->istate = tstate->interp;
#endif
internals_ptr->istate = tstate->interp;
state_dict[PYBIND11_INTERNALS_ID] = capsule(internals_pp);
internals_ptr->registered_exception_translators.push_front(&translate_exception);
internals_ptr->static_property_type = make_static_property_type();
@ -615,7 +581,7 @@ PYBIND11_NOINLINE internals &get_internals() {
struct local_internals {
type_map<type_info *> registered_types_cpp;
std::forward_list<ExceptionTranslator> registered_exception_translators;
#if defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
#if PYBIND11_INTERNALS_VERSION == 4
// For ABI compatibility, we can't store the loader_life_support TLS key in
// the `internals` struct directly. Instead, we store it in `shared_data` and
@ -648,7 +614,7 @@ struct local_internals {
loader_life_support_tls_key
= static_cast<shared_loader_life_support_data *>(ptr)->loader_life_support_tls_key;
}
#endif // defined(WITH_THREAD) && PYBIND11_INTERNALS_VERSION == 4
#endif // PYBIND11_INTERNALS_VERSION == 4
};
/// Works like `get_internals`, but for things which are locally registered.

View File

@ -36,14 +36,13 @@ private:
loader_life_support *parent = nullptr;
std::unordered_set<PyObject *> keep_alive;
#if defined(WITH_THREAD)
// Store stack pointer in thread-local storage.
static PYBIND11_TLS_KEY_REF get_stack_tls_key() {
# if PYBIND11_INTERNALS_VERSION == 4
#if PYBIND11_INTERNALS_VERSION == 4
return get_local_internals().loader_life_support_tls_key;
# else
#else
return get_internals().loader_life_support_tls_key;
# endif
#endif
}
static loader_life_support *get_stack_top() {
return static_cast<loader_life_support *>(PYBIND11_TLS_GET_VALUE(get_stack_tls_key()));
@ -51,15 +50,6 @@ private:
static void set_stack_top(loader_life_support *value) {
PYBIND11_TLS_REPLACE_VALUE(get_stack_tls_key(), value);
}
#else
// Use single global variable for stack.
static loader_life_support **get_stack_pp() {
static loader_life_support *global_stack = nullptr;
return global_stack;
}
static loader_life_support *get_stack_top() { return *get_stack_pp(); }
static void set_stack_top(loader_life_support *value) { *get_stack_pp() = value; }
#endif
public:
/// A new patient frame is created when a function is entered

View File

@ -103,9 +103,6 @@ inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
bool add_program_dir_to_path) {
detail::precheck_interpreter();
Py_InitializeEx(init_signal_handlers ? 1 : 0);
# if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
PyEval_InitThreads();
# endif
// Before it was special-cased in python 3.8, passing an empty or null argv
// caused a segfault, so we have to reimplement the special case ourselves.

View File

@ -13,7 +13,7 @@
#include <cassert>
#if defined(WITH_THREAD) && !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
#if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
# include "detail/internals.h"
#endif
@ -26,9 +26,7 @@ PyThreadState *get_thread_state_unchecked();
PYBIND11_NAMESPACE_END(detail)
#if defined(WITH_THREAD)
# if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
#if !defined(PYBIND11_SIMPLE_GIL_MANAGEMENT)
/* The functions below essentially reproduce the PyGILState_* API using a RAII
* pattern, but there are a few important differences:
@ -69,11 +67,11 @@ public:
if (!tstate) {
tstate = PyThreadState_New(internals.istate);
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
if (!tstate) {
pybind11_fail("scoped_acquire: could not create thread state!");
}
# endif
# endif
tstate->gilstate_counter = 0;
PYBIND11_TLS_REPLACE_VALUE(internals.tstate, tstate);
} else {
@ -94,20 +92,20 @@ public:
PYBIND11_NOINLINE void dec_ref() {
--tstate->gilstate_counter;
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
if (detail::get_thread_state_unchecked() != tstate) {
pybind11_fail("scoped_acquire::dec_ref(): thread state must be current!");
}
if (tstate->gilstate_counter < 0) {
pybind11_fail("scoped_acquire::dec_ref(): reference count underflow!");
}
# endif
# endif
if (tstate->gilstate_counter == 0) {
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
# if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
if (!release) {
pybind11_fail("scoped_acquire::dec_ref(): internal error!");
}
# endif
# endif
PyThreadState_Clear(tstate);
if (active) {
PyThreadState_DeleteCurrent();
@ -188,7 +186,7 @@ private:
bool active = true;
};
# else // PYBIND11_SIMPLE_GIL_MANAGEMENT
#else // PYBIND11_SIMPLE_GIL_MANAGEMENT
class gil_scoped_acquire {
PyGILState_STATE state;
@ -216,32 +214,6 @@ public:
void disarm() {}
};
# endif // PYBIND11_SIMPLE_GIL_MANAGEMENT
#else // WITH_THREAD
class gil_scoped_acquire {
public:
gil_scoped_acquire() {
// Trick to suppress `unused variable` error messages (at call sites).
(void) (this != (this + 1));
}
gil_scoped_acquire(const gil_scoped_acquire &) = delete;
gil_scoped_acquire &operator=(const gil_scoped_acquire &) = delete;
void disarm() {}
};
class gil_scoped_release {
public:
gil_scoped_release() {
// Trick to suppress `unused variable` error messages (at call sites).
(void) (this != (this + 1));
}
gil_scoped_release(const gil_scoped_release &) = delete;
gil_scoped_release &operator=(const gil_scoped_release &) = delete;
void disarm() {}
};
#endif // WITH_THREAD
#endif // PYBIND11_SIMPLE_GIL_MANAGEMENT
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)

View File

@ -14,8 +14,7 @@
#ifdef __has_include
# if defined(PYBIND11_CPP17)
# if __has_include(<filesystem>) && \
PY_VERSION_HEX >= 0x03060000
# if __has_include(<filesystem>)
# include <filesystem>
# define PYBIND11_HAS_FILESYSTEM 1
# elif __has_include(<experimental/filesystem>)

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import argparse
import nox

View File

@ -1,7 +1,9 @@
from __future__ import annotations
import sys
if sys.version_info < (3, 6): # noqa: UP036
msg = "pybind11 does not support Python < 3.6. 2.9 was the last release supporting Python 2.7 and 3.5."
if sys.version_info < (3, 7): # noqa: UP036
msg = "pybind11 does not support Python < 3.7. v2.12 was the last release supporting Python 3.6."
raise ImportError(msg)

View File

@ -1,4 +1,5 @@
# pylint: disable=missing-function-docstring
from __future__ import annotations
import argparse
import sys

View File

@ -1,7 +1,7 @@
from typing import Union
from __future__ import annotations
def _to_int(s: str) -> Union[int, str]:
def _to_int(s: str) -> int | str:
try:
return int(s)
except ValueError:

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import os
DIR = os.path.abspath(os.path.dirname(__file__))

View File

@ -36,6 +36,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# If you copy this file in, you don't
# need the .pyi file; it's just an interface file for static type checkers.
from __future__ import annotations
import contextlib
import os
@ -52,7 +53,6 @@ from pathlib import Path
from typing import (
Any,
Callable,
Dict,
Iterable,
Iterator,
List,
@ -113,10 +113,10 @@ class Pybind11Extension(_Extension):
# flags are prepended, so that they can be further overridden, e.g. by
# ``extra_compile_args=["-g"]``.
def _add_cflags(self, flags: List[str]) -> None:
def _add_cflags(self, flags: list[str]) -> None:
self.extra_compile_args[:0] = flags
def _add_ldflags(self, flags: List[str]) -> None:
def _add_ldflags(self, flags: list[str]) -> None:
self.extra_link_args[:0] = flags
def __init__(self, *args: Any, **kwargs: Any) -> None:
@ -250,7 +250,7 @@ cpp_flag_cache = None
@lru_cache()
def auto_cpp_level(compiler: Any) -> Union[str, int]:
def auto_cpp_level(compiler: Any) -> str | int:
"""
Return the max supported C++ std level (17, 14, or 11). Returns latest on Windows.
"""
@ -288,8 +288,8 @@ class build_ext(_build_ext): # noqa: N801
def intree_extensions(
paths: Iterable[str], package_dir: Optional[Dict[str, str]] = None
) -> List[Pybind11Extension]:
paths: Iterable[str], package_dir: dict[str, str] | None = None
) -> list[Pybind11Extension]:
"""
Generate Pybind11Extensions from source files directly located in a Python
source tree.
@ -409,7 +409,7 @@ class ParallelCompile:
def __init__(
self,
envvar: Optional[str] = None,
envvar: str | None = None,
default: int = 0,
max: int = 0, # pylint: disable=redefined-builtin
needs_recompile: Callable[[str, str], bool] = no_recompile,
@ -418,7 +418,7 @@ class ParallelCompile:
self.default = default
self.max = max
self.needs_recompile = needs_recompile
self._old: List[CCompilerMethod] = []
self._old: list[CCompilerMethod] = []
def function(self) -> CCompilerMethod:
"""
@ -427,14 +427,14 @@ class ParallelCompile:
def compile_function(
compiler: distutils.ccompiler.CCompiler,
sources: List[str],
output_dir: Optional[str] = None,
macros: Optional[List[Union[Tuple[str], Tuple[str, Optional[str]]]]] = None,
include_dirs: Optional[List[str]] = None,
sources: list[str],
output_dir: str | None = None,
macros: list[tuple[str] | tuple[str, str | None]] | None = None,
include_dirs: list[str] | None = None,
debug: bool = False,
extra_preargs: Optional[List[str]] = None,
extra_postargs: Optional[List[str]] = None,
depends: Optional[List[str]] = None,
extra_preargs: list[str] | None = None,
extra_postargs: list[str] | None = None,
depends: list[str] | None = None,
) -> Any:
# These lines are directly from distutils.ccompiler.CCompiler
macros, objects, extra_postargs, pp_opts, build = compiler._setup_compile( # type: ignore[attr-defined]

View File

@ -30,7 +30,7 @@ ignore_missing_imports = true
[tool.pylint]
master.py-version = "3.6"
master.py-version = "3.7"
reports.output-format = "colorized"
messages_control.disable = [
"design",
@ -76,6 +76,8 @@ ignore = [
]
unfixable = ["T20"]
isort.known-first-party = ["env", "pybind11_cross_module_tests", "pybind11_tests"]
isort.required-imports = ["from __future__ import annotations"]
[tool.ruff.lint.per-file-ignores]
"tests/**" = ["EM", "N", "E721"]

View File

@ -14,7 +14,6 @@ classifiers =
Topic :: Utilities
Programming Language :: C++
Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
@ -39,5 +38,5 @@ project_urls =
Chat = https://gitter.im/pybind/Lobby
[options]
python_requires = >=3.6
python_requires = >=3.7
zip_safe = False

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3
# Setup script for PyPI; use CMakeFile.txt to build extension modules
from __future__ import annotations
import contextlib
import os
@ -9,9 +10,9 @@ import shutil
import string
import subprocess
import sys
from collections.abc import Generator
from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Dict, Iterator, List, Union
import setuptools.command.sdist
@ -23,7 +24,7 @@ VERSION_FILE = Path("pybind11/_version.py")
COMMON_FILE = Path("include/pybind11/detail/common.h")
def build_expected_version_hex(matches: Dict[str, str]) -> str:
def build_expected_version_hex(matches: dict[str, str]) -> str:
patch_level_serial = matches["PATCH"]
serial = None
major = int(matches["MAJOR"])
@ -64,7 +65,7 @@ to_src = (
# Read the listed version
loc: Dict[str, str] = {}
loc: dict[str, str] = {}
code = compile(VERSION_FILE.read_text(encoding="utf-8"), "pybind11/_version.py", "exec")
exec(code, loc)
version = loc["__version__"]
@ -84,9 +85,7 @@ if version_hex != exp_version_hex:
# TODO: use literals & overload (typing extensions or Python 3.8)
def get_and_replace(
filename: Path, binary: bool = False, **opts: str
) -> Union[bytes, str]:
def get_and_replace(filename: Path, binary: bool = False, **opts: str) -> bytes | str:
if binary:
contents = filename.read_bytes()
return string.Template(contents.decode()).substitute(opts).encode()
@ -97,7 +96,7 @@ def get_and_replace(
# 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: str, files: List[str]) -> None:
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:
@ -112,7 +111,7 @@ class SDist(setuptools.command.sdist.sdist):
# Remove the CMake install directory when done
@contextlib.contextmanager
def remove_output(*sources: str) -> Iterator[None]:
def remove_output(*sources: str) -> Generator[None, None, None]:
try:
yield
finally:

View File

@ -4,6 +4,8 @@ Extends output capture as needed by pybind11: ignore constructors, optional unor
Adds docstring and exceptions message sanitizers.
"""
from __future__ import annotations
import contextlib
import difflib
import gc

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import platform
import sys
import sysconfig

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import contextlib
import os
import string

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import os
import subprocess
import sys

View File

@ -1,15 +1,13 @@
--only-binary=:all:
build~=0.9; python_version=="3.6"
build~=1.0; python_version>="3.7"
numpy~=1.20.0; python_version=="3.7" and platform_python_implementation=="PyPy"
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~=1.19.3; platform_python_implementation!="PyPy" and python_version=="3.6"
numpy~=1.21.5; platform_python_implementation!="PyPy" and python_version>="3.7" and python_version<"3.10"
numpy~=1.22.2; platform_python_implementation!="PyPy" and python_version=="3.10"
numpy~=1.26.0; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13"
pytest~=7.0
pytest-timeout
scipy~=1.5.4; platform_python_implementation!="PyPy" and python_version<"3.10"
scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10"
scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13"
scipy~=1.8.0; platform_python_implementation!="PyPy" and python_version=="3.10" and sys_platform!='win32'
scipy~=1.11.1; platform_python_implementation!="PyPy" and python_version>="3.11" and python_version<"3.13" and sys_platform!='win32'

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
asyncio = pytest.importorskip("asyncio")

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import ctypes
import io
import struct

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import pytest

View File

@ -95,7 +95,7 @@ TEST_SUBMODULE(call_policies, m) {
},
py::call_guard<DependentGuard, CustomGuard>());
#if defined(WITH_THREAD) && !defined(PYPY_VERSION)
#if !defined(PYPY_VERSION)
// `py::call_guard<py::gil_scoped_release>()` should work in PyPy as well,
// but it's unclear how to test it without `PyGILState_GetThisThreadState`.
auto report_gil_status = []() {

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
import env # noqa: F401

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import time
from threading import Thread

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import datetime
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from unittest import mock
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import test_cmake_build

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import const_name as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
m = pytest.importorskip("pybind11_tests.constants_and_functions")

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import copy_move_policies as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import custom_type_casters as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import gc
import weakref

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from pybind11_tests import docstring_options as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import ConstructorStats

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import sys
from widget_module import Widget

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import trampoline_module

View File

@ -1,4 +1,5 @@
# ruff: noqa: SIM201 SIM300 SIM202
from __future__ import annotations
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import os
import pytest

View File

@ -1,4 +1,5 @@
# This file is called from 'test_eval.py'
from __future__ import annotations
if "call_test2" in locals():
call_test2(y) # noqa: F821 undefined name

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import re
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import multiprocessing
import sys
import threading

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from contextlib import redirect_stderr, redirect_stdout
from io import StringIO

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import kwargs_and_defaults as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
import env # noqa: F401

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import sys
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import builtins
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
import env # noqa: F401

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
import env # noqa: F401
@ -198,11 +200,7 @@ def test_wrap():
assert a.flags.f_contiguous == b.flags.f_contiguous
assert a.flags.writeable == b.flags.writeable
assert a.flags.aligned == b.flags.aligned
# 1.13 supported Python 3.6
if tuple(int(x) for x in np.__version__.split(".")[:2]) >= (1, 14):
assert a.flags.writebackifcopy == b.flags.writebackifcopy
else:
assert a.flags.updateifcopy == b.flags.updateifcopy
assert a.flags.writebackifcopy == b.flags.writebackifcopy
assert np.all(a == b)
assert not b.flags.owndata
assert b.base is base

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import re
import pytest

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import numpy_vectorize as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import ConstructorStats, UserType

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import ConstructorStats

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pickle
import re

View File

@ -1,5 +1,6 @@
# Adapted from:
# https://github.com/google/clif/blob/5718e4d0807fd3b6a8187dde140069120b81ecef/clif/testing/python/python_multiple_inheritance_test.py
from __future__ import annotations
from pybind11_tests import python_multiple_inheritance as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import contextlib
import sys
import types

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pytest import approx # noqa: PT013

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
m = pytest.importorskip("pybind11_tests.smart_ptr")

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import ConstructorStats, UserType

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import stl_binders as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from pybind11_tests import tagbased_polymorphic as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import threading
from pybind11_tests import thread as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import type_caster_pyobject_ptr as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from pybind11_tests import union_ as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import unnamed_namespace_a as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
from pybind11_tests import unnamed_namespace_b as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
from pybind11_tests import vector_unique_ptr_member as m

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import pytest
import env # noqa: F401

View File

@ -92,7 +92,7 @@ endif()
# Use the Python interpreter to find the libs.
if(NOT PythonLibsNew_FIND_VERSION)
set(PythonLibsNew_FIND_VERSION "3.6")
set(PythonLibsNew_FIND_VERSION "3.7")
endif()
if(NOT CMAKE_VERSION VERSION_LESS "3.27")

View File

@ -9,11 +9,12 @@ python3 tools/codespell_ignore_lines_from_errors.py /tmp/codespell_errors.txt >
git diff to review changes, then commit, push.
"""
from __future__ import annotations
import sys
from typing import List
def run(args: List[str]) -> None:
def run(args: list[str]) -> None:
assert len(args) == 1, "codespell_errors.txt"
cache = {}
done = set()

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import os
import sys

View File

@ -56,7 +56,7 @@ if(NOT Python_FOUND AND NOT Python3_FOUND)
endif()
find_package(
Python 3.6 REQUIRED COMPONENTS ${_pybind11_interp_component} ${_pybind11_dev_component}
Python 3.7 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.

View File

@ -43,7 +43,7 @@ endif()
# A user can set versions manually too
set(Python_ADDITIONAL_VERSIONS
"3.12;3.11;3.10;3.9;3.8;3.7;3.6"
"3.12;3.11;3.10;3.9;3.8;3.7"
CACHE INTERNAL "")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")