aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/pybind11/tests
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/pybind11/tests')
-rw-r--r--3rdparty/pybind11/tests/CMakeLists.txt392
-rw-r--r--3rdparty/pybind11/tests/conftest.py96
-rw-r--r--3rdparty/pybind11/tests/constructor_stats.h3
-rw-r--r--3rdparty/pybind11/tests/env.py14
-rw-r--r--3rdparty/pybind11/tests/extra_python_package/pytest.ini0
-rw-r--r--3rdparty/pybind11/tests/extra_python_package/test_files.py262
-rw-r--r--3rdparty/pybind11/tests/extra_setuptools/pytest.ini0
-rw-r--r--3rdparty/pybind11/tests/extra_setuptools/test_setuphelper.py101
-rw-r--r--3rdparty/pybind11/tests/local_bindings.h2
-rw-r--r--3rdparty/pybind11/tests/pybind11_tests.cpp12
-rw-r--r--3rdparty/pybind11/tests/pybind11_tests.h20
-rw-r--r--3rdparty/pybind11/tests/pytest.ini7
-rw-r--r--3rdparty/pybind11/tests/requirements.txt8
-rw-r--r--3rdparty/pybind11/tests/test_async.cpp2
-rw-r--r--3rdparty/pybind11/tests/test_async.py6
-rw-r--r--3rdparty/pybind11/tests/test_buffers.cpp43
-rw-r--r--3rdparty/pybind11/tests/test_buffers.py90
-rw-r--r--3rdparty/pybind11/tests/test_builtin_casters.cpp4
-rw-r--r--3rdparty/pybind11/tests/test_builtin_casters.py192
-rw-r--r--3rdparty/pybind11/tests/test_call_policies.cpp1
-rw-r--r--3rdparty/pybind11/tests/test_call_policies.py60
-rw-r--r--3rdparty/pybind11/tests/test_callbacks.cpp6
-rw-r--r--3rdparty/pybind11/tests/test_callbacks.py32
-rw-r--r--3rdparty/pybind11/tests/test_chrono.cpp29
-rw-r--r--3rdparty/pybind11/tests/test_chrono.py60
-rw-r--r--3rdparty/pybind11/tests/test_class.cpp131
-rw-r--r--3rdparty/pybind11/tests/test_class.py245
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/CMakeLists.txt83
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/embed.cpp4
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt23
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt38
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt45
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt38
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt38
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt41
-rw-r--r--3rdparty/pybind11/tests/test_cmake_build/test.py1
-rw-r--r--3rdparty/pybind11/tests/test_constants_and_functions.cpp2
-rw-r--r--3rdparty/pybind11/tests/test_constants_and_functions.py5
-rw-r--r--3rdparty/pybind11/tests/test_copy_move.cpp34
-rw-r--r--3rdparty/pybind11/tests/test_copy_move.py21
-rw-r--r--3rdparty/pybind11/tests/test_custom_type_casters.cpp127
-rw-r--r--3rdparty/pybind11/tests/test_custom_type_casters.py116
-rw-r--r--3rdparty/pybind11/tests/test_docstring_options.py11
-rw-r--r--3rdparty/pybind11/tests/test_eigen.cpp13
-rw-r--r--3rdparty/pybind11/tests/test_eigen.py314
-rw-r--r--3rdparty/pybind11/tests/test_embed/CMakeLists.txt44
-rw-r--r--3rdparty/pybind11/tests/test_embed/test_interpreter.cpp52
-rw-r--r--3rdparty/pybind11/tests/test_embed/test_interpreter.py1
-rw-r--r--3rdparty/pybind11/tests/test_enum.py43
-rw-r--r--3rdparty/pybind11/tests/test_eval.cpp10
-rw-r--r--3rdparty/pybind11/tests/test_eval.py20
-rw-r--r--3rdparty/pybind11/tests/test_eval_call.py3
-rw-r--r--3rdparty/pybind11/tests/test_exceptions.cpp42
-rw-r--r--3rdparty/pybind11/tests/test_exceptions.py52
-rw-r--r--3rdparty/pybind11/tests/test_factory_constructors.cpp19
-rw-r--r--3rdparty/pybind11/tests/test_factory_constructors.py133
-rw-r--r--3rdparty/pybind11/tests/test_gil_scoped.cpp10
-rw-r--r--3rdparty/pybind11/tests/test_gil_scoped.py11
-rw-r--r--3rdparty/pybind11/tests/test_iostream.cpp8
-rw-r--r--3rdparty/pybind11/tests/test_iostream.py48
-rw-r--r--3rdparty/pybind11/tests/test_kwargs_and_defaults.cpp44
-rw-r--r--3rdparty/pybind11/tests/test_kwargs_and_defaults.py178
-rw-r--r--3rdparty/pybind11/tests/test_local_bindings.cpp2
-rw-r--r--3rdparty/pybind11/tests/test_local_bindings.py56
-rw-r--r--3rdparty/pybind11/tests/test_methods_and_attributes.cpp145
-rw-r--r--3rdparty/pybind11/tests/test_methods_and_attributes.py223
-rw-r--r--3rdparty/pybind11/tests/test_modules.cpp5
-rw-r--r--3rdparty/pybind11/tests/test_modules.py11
-rw-r--r--3rdparty/pybind11/tests/test_multiple_inheritance.cpp2
-rw-r--r--3rdparty/pybind11/tests/test_multiple_inheritance.py28
-rw-r--r--3rdparty/pybind11/tests/test_numpy_array.cpp112
-rw-r--r--3rdparty/pybind11/tests/test_numpy_array.py296
-rw-r--r--3rdparty/pybind11/tests/test_numpy_dtypes.cpp39
-rw-r--r--3rdparty/pybind11/tests/test_numpy_dtypes.py311
-rw-r--r--3rdparty/pybind11/tests/test_numpy_vectorize.cpp14
-rw-r--r--3rdparty/pybind11/tests/test_numpy_vectorize.py168
-rw-r--r--3rdparty/pybind11/tests/test_opaque_types.cpp8
-rw-r--r--3rdparty/pybind11/tests/test_opaque_types.py14
-rw-r--r--3rdparty/pybind11/tests/test_operator_overloading.cpp63
-rw-r--r--3rdparty/pybind11/tests/test_operator_overloading.py61
-rw-r--r--3rdparty/pybind11/tests/test_pickling.py7
-rw-r--r--3rdparty/pybind11/tests/test_pytypes.cpp113
-rw-r--r--3rdparty/pybind11/tests/test_pytypes.py263
-rw-r--r--3rdparty/pybind11/tests/test_sequences_and_iterators.cpp9
-rw-r--r--3rdparty/pybind11/tests/test_sequences_and_iterators.py52
-rw-r--r--3rdparty/pybind11/tests/test_smart_ptr.cpp16
-rw-r--r--3rdparty/pybind11/tests/test_smart_ptr.py58
-rw-r--r--3rdparty/pybind11/tests/test_stl.cpp44
-rw-r--r--3rdparty/pybind11/tests/test_stl.py69
-rw-r--r--3rdparty/pybind11/tests/test_stl_binders.cpp2
-rw-r--r--3rdparty/pybind11/tests/test_stl_binders.py107
-rw-r--r--3rdparty/pybind11/tests/test_tagbased_polymorphic.cpp8
-rw-r--r--3rdparty/pybind11/tests/test_tagbased_polymorphic.py15
-rw-r--r--3rdparty/pybind11/tests/test_union.py1
-rw-r--r--3rdparty/pybind11/tests/test_virtual_functions.cpp101
-rw-r--r--3rdparty/pybind11/tests/test_virtual_functions.py72
96 files changed, 4431 insertions, 1554 deletions
diff --git a/3rdparty/pybind11/tests/CMakeLists.txt b/3rdparty/pybind11/tests/CMakeLists.txt
index 765c47ad..dae8b5ad 100644
--- a/3rdparty/pybind11/tests/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/CMakeLists.txt
@@ -5,78 +5,150 @@
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.4)
-option(PYBIND11_WERROR "Report all warnings as errors" OFF)
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
+
+# Only needed for CMake < 3.5 support
+include(CMakeParseArguments)
+
+# Filter out items; print an optional message if any items filtered
+#
+# Usage:
+# pybind11_filter_tests(LISTNAME file1.cpp file2.cpp ... MESSAGE "")
+#
+macro(PYBIND11_FILTER_TESTS LISTNAME)
+ cmake_parse_arguments(ARG "" "MESSAGE" "" ${ARGN})
+ set(PYBIND11_FILTER_TESTS_FOUND OFF)
+ foreach(filename IN LISTS ARG_UNPARSED_ARGUMENTS)
+ list(FIND ${LISTNAME} ${filename} _FILE_FOUND)
+ if(_FILE_FOUND GREATER -1)
+ list(REMOVE_AT ${LISTNAME} ${_FILE_FOUND})
+ set(PYBIND11_FILTER_TESTS_FOUND ON)
+ endif()
+ endforeach()
+ if(PYBIND11_FILTER_TESTS_FOUND AND ARG_MESSAGE)
+ message(STATUS "${ARG_MESSAGE}")
+ endif()
+endmacro()
-if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
- # We're being loaded directly, i.e. not via add_subdirectory, so make this
- # work as its own project and load the pybind11Config to get the tools we need
- project(pybind11_tests CXX)
+# New Python support
+if(DEFINED Python_EXECUTABLE)
+ set(PYTHON_EXECUTABLE "${Python_EXECUTABLE}")
+ set(PYTHON_VERSION "${Python_VERSION}")
+endif()
- find_package(pybind11 REQUIRED CONFIG)
+# There's no harm in including a project in a project
+project(pybind11_tests CXX)
+
+# Access FindCatch and more
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../tools")
+
+option(PYBIND11_WERROR "Report all warnings as errors" OFF)
+option(DOWNLOAD_EIGEN "Download EIGEN (requires CMake 3.11+)" OFF)
+option(PYBIND11_CUDA_TESTS "Enable building CUDA tests (requires CMake 3.12+)" OFF)
+set(PYBIND11_TEST_OVERRIDE
+ ""
+ CACHE STRING "Tests from ;-separated list of *.cpp files will be built instead of all tests")
+set(PYBIND11_TEST_FILTER
+ ""
+ CACHE STRING "Tests from ;-separated list of *.cpp files will be removed from all tests")
+
+if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+ # We're being loaded directly, i.e. not via add_subdirectory, so make this
+ # work as its own project and load the pybind11Config to get the tools we need
+ find_package(pybind11 REQUIRED CONFIG)
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting tests build type to MinSizeRel as none was specified")
- set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "Choose the type of build." FORCE)
- set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
- "MinSizeRel" "RelWithDebInfo")
+ set(CMAKE_BUILD_TYPE
+ MinSizeRel
+ CACHE STRING "Choose the type of build." FORCE)
+ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel"
+ "RelWithDebInfo")
+endif()
+
+if(PYBIND11_CUDA_TESTS)
+ enable_language(CUDA)
+ if(DEFINED CMAKE_CXX_STANDARD)
+ set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD})
+ endif()
+ set(CMAKE_CUDA_STANDARD_REQUIRED ON)
endif()
# Full set of test files (you can override these; see below)
set(PYBIND11_TEST_FILES
- test_async.cpp
- test_buffers.cpp
- test_builtin_casters.cpp
- test_call_policies.cpp
- test_callbacks.cpp
- test_chrono.cpp
- test_class.cpp
- test_constants_and_functions.cpp
- test_copy_move.cpp
- test_docstring_options.cpp
- test_eigen.cpp
- test_enum.cpp
- test_eval.cpp
- test_exceptions.cpp
- test_factory_constructors.cpp
- test_gil_scoped.cpp
- test_iostream.cpp
- test_kwargs_and_defaults.cpp
- test_local_bindings.cpp
- test_methods_and_attributes.cpp
- test_modules.cpp
- test_multiple_inheritance.cpp
- test_numpy_array.cpp
- test_numpy_dtypes.cpp
- test_numpy_vectorize.cpp
- test_opaque_types.cpp
- test_operator_overloading.cpp
- test_pickling.cpp
- test_pytypes.cpp
- test_sequences_and_iterators.cpp
- test_smart_ptr.cpp
- test_stl.cpp
- test_stl_binders.cpp
- test_tagbased_polymorphic.cpp
- test_union.cpp
- test_virtual_functions.cpp
-)
+ test_async.cpp
+ test_buffers.cpp
+ test_builtin_casters.cpp
+ test_call_policies.cpp
+ test_callbacks.cpp
+ test_chrono.cpp
+ test_class.cpp
+ test_constants_and_functions.cpp
+ test_copy_move.cpp
+ test_custom_type_casters.cpp
+ test_docstring_options.cpp
+ test_eigen.cpp
+ test_enum.cpp
+ test_eval.cpp
+ test_exceptions.cpp
+ test_factory_constructors.cpp
+ test_gil_scoped.cpp
+ test_iostream.cpp
+ test_kwargs_and_defaults.cpp
+ test_local_bindings.cpp
+ test_methods_and_attributes.cpp
+ test_modules.cpp
+ test_multiple_inheritance.cpp
+ test_numpy_array.cpp
+ test_numpy_dtypes.cpp
+ test_numpy_vectorize.cpp
+ test_opaque_types.cpp
+ test_operator_overloading.cpp
+ test_pickling.cpp
+ test_pytypes.cpp
+ test_sequences_and_iterators.cpp
+ test_smart_ptr.cpp
+ test_stl.cpp
+ test_stl_binders.cpp
+ test_tagbased_polymorphic.cpp
+ test_union.cpp
+ test_virtual_functions.cpp)
# Invoking cmake with something like:
-# cmake -DPYBIND11_TEST_OVERRIDE="test_callbacks.cpp;test_picking.cpp" ..
+# cmake -DPYBIND11_TEST_OVERRIDE="test_callbacks.cpp;test_pickling.cpp" ..
# lets you override the tests that get compiled and run. You can restore to all tests with:
# cmake -DPYBIND11_TEST_OVERRIDE= ..
-if (PYBIND11_TEST_OVERRIDE)
+if(PYBIND11_TEST_OVERRIDE)
set(PYBIND11_TEST_FILES ${PYBIND11_TEST_OVERRIDE})
endif()
-# Skip test_async for Python < 3.5
-list(FIND PYBIND11_TEST_FILES test_async.cpp PYBIND11_TEST_FILES_ASYNC_I)
-if((PYBIND11_TEST_FILES_ASYNC_I GREATER -1) AND ("${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" VERSION_LESS 3.5))
- message(STATUS "Skipping test_async because Python version ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} < 3.5")
- list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_ASYNC_I})
+# You can also filter tests:
+if(PYBIND11_TEST_FILTER)
+ pybind11_filter_tests(PYBIND11_TEST_FILES ${PYBIND11_TEST_FILTER})
+endif()
+
+if(PYTHON_VERSION VERSION_LESS 3.5)
+ pybind11_filter_tests(PYBIND11_TEST_FILES test_async.cpp MESSAGE
+ "Skipping test_async on Python 2")
+endif()
+
+# Skip tests for CUDA check:
+# /pybind11/tests/test_constants_and_functions.cpp(125):
+# error: incompatible exception specifications
+if(PYBIND11_CUDA_TESTS)
+ pybind11_filter_tests(
+ PYBIND11_TEST_FILES test_constants_and_functions.cpp MESSAGE
+ "Skipping test_constants_and_functions due to incompatible exception specifications")
endif()
string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}")
@@ -84,16 +156,10 @@ string(REPLACE ".cpp" ".py" PYBIND11_PYTEST_FILES "${PYBIND11_TEST_FILES}")
# Contains the set of test files that require pybind11_cross_module_tests to be
# built; if none of these are built (i.e. because TEST_OVERRIDE is used and
# doesn't include them) the second module doesn't get built.
-set(PYBIND11_CROSS_MODULE_TESTS
- test_exceptions.py
- test_local_bindings.py
- test_stl.py
- test_stl_binders.py
-)
+set(PYBIND11_CROSS_MODULE_TESTS test_exceptions.py test_local_bindings.py test_stl.py
+ test_stl_binders.py)
-set(PYBIND11_CROSS_MODULE_GIL_TESTS
- test_gil_scoped.py
-)
+set(PYBIND11_CROSS_MODULE_GIL_TESTS test_gil_scoped.py)
# Check if Eigen is available; if not, remove from PYBIND11_TEST_FILES (but
# keep it in PYBIND11_PYTEST_FILES, so that we get the "eigen is not installed"
@@ -103,21 +169,45 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
# Try loading via newer Eigen's Eigen3Config first (bypassing tools/FindEigen3.cmake).
# Eigen 3.3.1+ exports a cmake 3.0+ target for handling dependency requirements, but also
# produces a fatal error if loaded from a pre-3.0 cmake.
- if (NOT CMAKE_VERSION VERSION_LESS 3.0)
+ if(DOWNLOAD_EIGEN)
+ if(CMAKE_VERSION VERSION_LESS 3.11)
+ message(FATAL_ERROR "CMake 3.11+ required when using DOWNLOAD_EIGEN")
+ endif()
+
+ set(EIGEN3_VERSION_STRING "3.3.8")
+
+ include(FetchContent)
+ FetchContent_Declare(
+ eigen
+ GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
+ GIT_TAG ${EIGEN3_VERSION_STRING})
+
+ FetchContent_GetProperties(eigen)
+ if(NOT eigen_POPULATED)
+ message(STATUS "Downloading Eigen")
+ FetchContent_Populate(eigen)
+ endif()
+
+ set(EIGEN3_INCLUDE_DIR ${eigen_SOURCE_DIR})
+ set(EIGEN3_FOUND TRUE)
+
+ else()
find_package(Eigen3 3.2.7 QUIET CONFIG)
- if (EIGEN3_FOUND)
- if (EIGEN3_VERSION_STRING AND NOT EIGEN3_VERSION_STRING VERSION_LESS 3.3.1)
- set(PYBIND11_EIGEN_VIA_TARGET 1)
- endif()
+
+ if(NOT EIGEN3_FOUND)
+ # Couldn't load via target, so fall back to allowing module mode finding, which will pick up
+ # tools/FindEigen3.cmake
+ find_package(Eigen3 3.2.7 QUIET)
endif()
endif()
- if (NOT EIGEN3_FOUND)
- # Couldn't load via target, so fall back to allowing module mode finding, which will pick up
- # tools/FindEigen3.cmake
- find_package(Eigen3 3.2.7 QUIET)
- endif()
if(EIGEN3_FOUND)
+ if(NOT TARGET Eigen3::Eigen)
+ add_library(Eigen3::Eigen IMPORTED INTERFACE)
+ set_property(TARGET Eigen3::Eigen PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ "${EIGEN3_INCLUDE_DIR}")
+ endif()
+
# Eigen 3.3.1+ cmake sets EIGEN3_VERSION_STRING (and hard codes the version when installed
# rather than looking it up in the cmake script); older versions, and the
# tools/FindEigen3.cmake, set EIGEN3_VERSION instead.
@@ -127,28 +217,63 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
message(STATUS "Building tests with Eigen v${EIGEN3_VERSION}")
else()
list(REMOVE_AT PYBIND11_TEST_FILES ${PYBIND11_TEST_FILES_EIGEN_I})
- message(STATUS "Building tests WITHOUT Eigen")
+ message(STATUS "Building tests WITHOUT Eigen, use -DDOWNLOAD_EIGEN on CMake 3.11+ to download")
endif()
endif()
# Optional dependency for some tests (boost::variant is only supported with version >= 1.56)
find_package(Boost 1.56)
+if(Boost_FOUND)
+ if(NOT TARGET Boost::headers)
+ add_library(Boost::headers IMPORTED INTERFACE)
+ if(TARGET Boost::boost)
+ # Classic FindBoost
+ set_property(TARGET Boost::boost PROPERTY INTERFACE_LINK_LIBRARIES Boost::boost)
+ else()
+ # Very old FindBoost, or newer Boost than CMake in older CMakes
+ set_property(TARGET Boost::headers PROPERTY INTERFACE_INCLUDE_DIRECTORIES
+ ${Boost_INCLUDE_DIRS})
+ endif()
+ endif()
+endif()
+
# Compile with compiler warnings turned on
function(pybind11_enable_warnings target_name)
if(MSVC)
target_compile_options(${target_name} PRIVATE /W4)
- elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Intel|Clang)")
- target_compile_options(${target_name} PRIVATE -Wall -Wextra -Wconversion -Wcast-qual -Wdeprecated)
+ elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Intel|Clang)" AND NOT PYBIND11_CUDA_TESTS)
+ target_compile_options(
+ ${target_name}
+ PRIVATE -Wall
+ -Wextra
+ -Wconversion
+ -Wcast-qual
+ -Wdeprecated
+ -Wundef
+ -Wnon-virtual-dtor)
endif()
if(PYBIND11_WERROR)
if(MSVC)
target_compile_options(${target_name} PRIVATE /WX)
+ elseif(PYBIND11_CUDA_TESTS)
+ target_compile_options(${target_name} PRIVATE "SHELL:-Werror all-warnings")
elseif(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Intel|Clang)")
target_compile_options(${target_name} PRIVATE -Werror)
endif()
endif()
+
+ # Needs to be readded since the ordering requires these to be after the ones above
+ if(CMAKE_CXX_STANDARD
+ AND CMAKE_CXX_COMPILER_ID MATCHES "Clang"
+ AND PYTHON_VERSION VERSION_LESS 3.0)
+ if(CMAKE_CXX_STANDARD LESS 17)
+ target_compile_options(${target_name} PUBLIC -Wno-deprecated-register)
+ else()
+ target_compile_options(${target_name} PUBLIC -Wno-register)
+ endif()
+ endif()
endfunction()
set(test_targets pybind11_tests)
@@ -156,7 +281,7 @@ set(test_targets pybind11_tests)
# Build pybind11_cross_module_tests if any test_whatever.py are being built that require it
foreach(t ${PYBIND11_CROSS_MODULE_TESTS})
list(FIND PYBIND11_PYTEST_FILES ${t} i)
- if (i GREATER -1)
+ if(i GREATER -1)
list(APPEND test_targets pybind11_cross_module_tests)
break()
endif()
@@ -164,78 +289,101 @@ endforeach()
foreach(t ${PYBIND11_CROSS_MODULE_GIL_TESTS})
list(FIND PYBIND11_PYTEST_FILES ${t} i)
- if (i GREATER -1)
+ if(i GREATER -1)
list(APPEND test_targets cross_module_gil_utils)
break()
endif()
endforeach()
-set(testdir ${CMAKE_CURRENT_SOURCE_DIR})
+# Support CUDA testing by forcing the target file to compile with NVCC
+if(PYBIND11_CUDA_TESTS)
+ set_property(SOURCE ${PYBIND11_TEST_FILES} PROPERTY LANGUAGE CUDA)
+endif()
+
foreach(target ${test_targets})
set(test_files ${PYBIND11_TEST_FILES})
- if(NOT target STREQUAL "pybind11_tests")
+ if(NOT "${target}" STREQUAL "pybind11_tests")
set(test_files "")
endif()
+ # Support CUDA testing by forcing the target file to compile with NVCC
+ if(PYBIND11_CUDA_TESTS)
+ set_property(SOURCE ${target}.cpp PROPERTY LANGUAGE CUDA)
+ endif()
+
# Create the binding library
pybind11_add_module(${target} THIN_LTO ${target}.cpp ${test_files} ${PYBIND11_HEADERS})
pybind11_enable_warnings(${target})
+ if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ get_property(
+ suffix
+ TARGET ${target}
+ PROPERTY SUFFIX)
+ set(source_output "${CMAKE_CURRENT_SOURCE_DIR}/${target}${suffix}")
+ if(suffix AND EXISTS "${source_output}")
+ message(WARNING "Output file also in source directory; "
+ "please remove to avoid confusion: ${source_output}")
+ endif()
+ endif()
+
if(MSVC)
target_compile_options(${target} PRIVATE /utf-8)
endif()
if(EIGEN3_FOUND)
- if (PYBIND11_EIGEN_VIA_TARGET)
- target_link_libraries(${target} PRIVATE Eigen3::Eigen)
- else()
- target_include_directories(${target} PRIVATE ${EIGEN3_INCLUDE_DIR})
- endif()
+ target_link_libraries(${target} PRIVATE Eigen3::Eigen)
target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_EIGEN)
endif()
if(Boost_FOUND)
- target_include_directories(${target} PRIVATE ${Boost_INCLUDE_DIRS})
+ target_link_libraries(${target} PRIVATE Boost::headers)
target_compile_definitions(${target} PRIVATE -DPYBIND11_TEST_BOOST)
endif()
# Always write the output file directly into the 'tests' directory (even on MSVC)
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
- set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${testdir})
+ set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+ "${CMAKE_CURRENT_BINARY_DIR}")
foreach(config ${CMAKE_CONFIGURATION_TYPES})
string(TOUPPER ${config} config)
- set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config} ${testdir})
+ set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config}
+ "${CMAKE_CURRENT_BINARY_DIR}")
endforeach()
endif()
endforeach()
-# Make sure pytest is found or produce a fatal error
-if(NOT PYBIND11_PYTEST_FOUND)
- execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import pytest; print(pytest.__version__)"
- RESULT_VARIABLE pytest_not_found OUTPUT_VARIABLE pytest_version ERROR_QUIET)
- if(pytest_not_found)
- message(FATAL_ERROR "Running the tests requires pytest. Please install it manually"
- " (try: ${PYTHON_EXECUTABLE} -m pip install pytest)")
- elseif(pytest_version VERSION_LESS 3.0)
- message(FATAL_ERROR "Running the tests requires pytest >= 3.0. Found: ${pytest_version}"
- "Please update it (try: ${PYTHON_EXECUTABLE} -m pip install -U pytest)")
- endif()
- set(PYBIND11_PYTEST_FOUND TRUE CACHE INTERNAL "")
-endif()
+# Make sure pytest is found or produce a warning
+pybind11_find_import(pytest VERSION 3.1)
+
+if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ # This is not used later in the build, so it's okay to regenerate each time.
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pytest.ini" "${CMAKE_CURRENT_BINARY_DIR}/pytest.ini"
+ COPYONLY)
+ file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pytest.ini"
+ "\ntestpaths = \"${CMAKE_CURRENT_SOURCE_DIR}\"")
-if(CMAKE_VERSION VERSION_LESS 3.2)
- set(PYBIND11_USES_TERMINAL "")
-else()
- set(PYBIND11_USES_TERMINAL "USES_TERMINAL")
endif()
+# cmake 3.12 added list(transform <list> prepend
+# but we can't use it yet
+string(REPLACE "test_" "${CMAKE_CURRENT_SOURCE_DIR}/test_" PYBIND11_ABS_PYTEST_FILES
+ "${PYBIND11_PYTEST_FILES}")
+
# A single command to compile and run the tests
-add_custom_target(pytest COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_PYTEST_FILES}
- DEPENDS ${test_targets} WORKING_DIRECTORY ${testdir} ${PYBIND11_USES_TERMINAL})
+add_custom_target(
+ pytest
+ COMMAND ${PYTHON_EXECUTABLE} -m pytest ${PYBIND11_ABS_PYTEST_FILES}
+ DEPENDS ${test_targets}
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ USES_TERMINAL)
if(PYBIND11_TEST_OVERRIDE)
- add_custom_command(TARGET pytest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E echo "Note: not all tests run: -DPYBIND11_TEST_OVERRIDE is in effect")
+ add_custom_command(
+ TARGET pytest
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E echo
+ "Note: not all tests run: -DPYBIND11_TEST_OVERRIDE is in effect")
endif()
# Add a check target to run all the tests, starting with pytest (we add dependencies to this below)
@@ -243,17 +391,23 @@ add_custom_target(check DEPENDS pytest)
# The remaining tests only apply when being built as part of the pybind11 project, but not if the
# tests are being built independently.
-if (NOT PROJECT_NAME STREQUAL "pybind11")
+if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
return()
endif()
# Add a post-build comment to show the primary test suite .so size and, if a previous size, compare it:
-add_custom_command(TARGET pybind11_tests POST_BUILD
- COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/libsize.py
- $<TARGET_FILE:pybind11_tests> ${CMAKE_CURRENT_BINARY_DIR}/sosize-$<TARGET_FILE_NAME:pybind11_tests>.txt)
-
-# Test embedding the interpreter. Provides the `cpptest` target.
-add_subdirectory(test_embed)
-
-# Test CMake build using functions and targets from subdirectory or installed location
-add_subdirectory(test_cmake_build)
+add_custom_command(
+ TARGET pybind11_tests
+ POST_BUILD
+ COMMAND
+ ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/../tools/libsize.py
+ $<TARGET_FILE:pybind11_tests>
+ ${CMAKE_CURRENT_BINARY_DIR}/sosize-$<TARGET_FILE_NAME:pybind11_tests>.txt)
+
+if(NOT PYBIND11_CUDA_TESTS)
+ # Test embedding the interpreter. Provides the `cpptest` target.
+ add_subdirectory(test_embed)
+
+ # Test CMake build using functions and targets from subdirectory or installed location
+ add_subdirectory(test_cmake_build)
+endif()
diff --git a/3rdparty/pybind11/tests/conftest.py b/3rdparty/pybind11/tests/conftest.py
index 57f681c6..362eb806 100644
--- a/3rdparty/pybind11/tests/conftest.py
+++ b/3rdparty/pybind11/tests/conftest.py
@@ -1,31 +1,36 @@
+# -*- coding: utf-8 -*-
"""pytest configuration
Extends output capture as needed by pybind11: ignore constructors, optional unordered lines.
Adds docstring and exceptions message sanitizers: ignore Python 2 vs 3 differences.
"""
-import pytest
-import textwrap
-import difflib
-import re
-import sys
import contextlib
-import platform
+import difflib
import gc
+import re
+import textwrap
+
+import pytest
-_unicode_marker = re.compile(r'u(\'[^\']*\')')
-_long_marker = re.compile(r'([0-9])L')
-_hexadecimal = re.compile(r'0x[0-9a-fA-F]+')
+import env
-# test_async.py requires support for async and await
+# Early diagnostic for failed imports
+import pybind11_tests # noqa: F401
+
+_unicode_marker = re.compile(r"u(\'[^\']*\')")
+_long_marker = re.compile(r"([0-9])L")
+_hexadecimal = re.compile(r"0x[0-9a-fA-F]+")
+
+# Avoid collecting Python3 only files
collect_ignore = []
-if sys.version_info[:2] < (3, 5):
+if env.PY2:
collect_ignore.append("test_async.py")
def _strip_and_dedent(s):
"""For triple-quote strings"""
- return textwrap.dedent(s.lstrip('\n').rstrip())
+ return textwrap.dedent(s.lstrip("\n").rstrip())
def _split_and_sort(s):
@@ -35,11 +40,14 @@ def _split_and_sort(s):
def _make_explanation(a, b):
"""Explanation for a failed assert -- the a and b arguments are List[str]"""
- return ["--- actual / +++ expected"] + [line.strip('\n') for line in difflib.ndiff(a, b)]
+ return ["--- actual / +++ expected"] + [
+ line.strip("\n") for line in difflib.ndiff(a, b)
+ ]
class Output(object):
"""Basic output post-processing and comparison"""
+
def __init__(self, string):
self.string = string
self.explanation = []
@@ -49,7 +57,11 @@ class Output(object):
def __eq__(self, other):
# Ignore constructor/destructor output which is prefixed with "###"
- a = [line for line in self.string.strip().splitlines() if not line.startswith("###")]
+ a = [
+ line
+ for line in self.string.strip().splitlines()
+ if not line.startswith("###")
+ ]
b = _strip_and_dedent(other).splitlines()
if a == b:
return True
@@ -60,6 +72,7 @@ class Output(object):
class Unordered(Output):
"""Custom comparison for output without strict line ordering"""
+
def __eq__(self, other):
a = _split_and_sort(self.string)
b = _split_and_sort(other)
@@ -170,7 +183,7 @@ def msg():
# noinspection PyUnusedLocal
def pytest_assertrepr_compare(op, left, right):
"""Hook to insert custom failure explanation"""
- if hasattr(left, 'explanation'):
+ if hasattr(left, "explanation"):
return left.explanation
@@ -184,61 +197,12 @@ def suppress(exception):
def gc_collect():
- ''' Run the garbage collector twice (needed when running
- reference counting tests with PyPy) '''
+ """Run the garbage collector twice (needed when running
+ reference counting tests with PyPy)"""
gc.collect()
gc.collect()
def pytest_configure():
- """Add import suppression and test requirements to `pytest` namespace"""
- try:
- import numpy as np
- except ImportError:
- np = None
- try:
- import scipy
- except ImportError:
- scipy = None
- try:
- from pybind11_tests.eigen import have_eigen
- except ImportError:
- have_eigen = False
- pypy = platform.python_implementation() == "PyPy"
-
- skipif = pytest.mark.skipif
pytest.suppress = suppress
- pytest.requires_numpy = skipif(not np, reason="numpy is not installed")
- pytest.requires_scipy = skipif(not np, reason="scipy is not installed")
- pytest.requires_eigen_and_numpy = skipif(not have_eigen or not np,
- reason="eigen and/or numpy are not installed")
- pytest.requires_eigen_and_scipy = skipif(
- not have_eigen or not scipy, reason="eigen and/or scipy are not installed")
- pytest.unsupported_on_pypy = skipif(pypy, reason="unsupported on PyPy")
- pytest.unsupported_on_py2 = skipif(sys.version_info.major < 3,
- reason="unsupported on Python 2.x")
pytest.gc_collect = gc_collect
-
-
-def _test_import_pybind11():
- """Early diagnostic for test module initialization errors
-
- When there is an error during initialization, the first import will report the
- real error while all subsequent imports will report nonsense. This import test
- is done early (in the pytest configuration file, before any tests) in order to
- avoid the noise of having all tests fail with identical error messages.
-
- Any possible exception is caught here and reported manually *without* the stack
- trace. This further reduces noise since the trace would only show pytest internals
- which are not useful for debugging pybind11 module issues.
- """
- # noinspection PyBroadException
- try:
- import pybind11_tests # noqa: F401 imported but unused
- except Exception as e:
- print("Failed to import pybind11_tests from pytest:")
- print(" {}: {}".format(type(e).__name__, e))
- sys.exit(1)
-
-
-_test_import_pybind11()
diff --git a/3rdparty/pybind11/tests/constructor_stats.h b/3rdparty/pybind11/tests/constructor_stats.h
index 431e5ace..805968a0 100644
--- a/3rdparty/pybind11/tests/constructor_stats.h
+++ b/3rdparty/pybind11/tests/constructor_stats.h
@@ -120,7 +120,7 @@ public:
throw py::error_already_set();
Py_DECREF(result);
#else
- py::module::import("gc").attr("collect")();
+ py::module_::import("gc").attr("collect")();
#endif
}
@@ -273,4 +273,3 @@ template <class T, typename... Values> void print_values(T *inst, Values &&...va
print_constr_details(inst, ":", values...);
track_values(inst, values...);
}
-
diff --git a/3rdparty/pybind11/tests/env.py b/3rdparty/pybind11/tests/env.py
new file mode 100644
index 00000000..5cded441
--- /dev/null
+++ b/3rdparty/pybind11/tests/env.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+import platform
+import sys
+
+LINUX = sys.platform.startswith("linux")
+MACOS = sys.platform.startswith("darwin")
+WIN = sys.platform.startswith("win32") or sys.platform.startswith("cygwin")
+
+CPYTHON = platform.python_implementation() == "CPython"
+PYPY = platform.python_implementation() == "PyPy"
+
+PY2 = sys.version_info.major == 2
+
+PY = sys.version_info
diff --git a/3rdparty/pybind11/tests/extra_python_package/pytest.ini b/3rdparty/pybind11/tests/extra_python_package/pytest.ini
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/3rdparty/pybind11/tests/extra_python_package/pytest.ini
diff --git a/3rdparty/pybind11/tests/extra_python_package/test_files.py b/3rdparty/pybind11/tests/extra_python_package/test_files.py
new file mode 100644
index 00000000..cbd4bff1
--- /dev/null
+++ b/3rdparty/pybind11/tests/extra_python_package/test_files.py
@@ -0,0 +1,262 @@
+# -*- coding: utf-8 -*-
+import contextlib
+import os
+import string
+import subprocess
+import sys
+import tarfile
+import zipfile
+
+# These tests must be run explicitly
+# They require CMake 3.15+ (--install)
+
+DIR = os.path.abspath(os.path.dirname(__file__))
+MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
+
+
+main_headers = {
+ "include/pybind11/attr.h",
+ "include/pybind11/buffer_info.h",
+ "include/pybind11/cast.h",
+ "include/pybind11/chrono.h",
+ "include/pybind11/common.h",
+ "include/pybind11/complex.h",
+ "include/pybind11/eigen.h",
+ "include/pybind11/embed.h",
+ "include/pybind11/eval.h",
+ "include/pybind11/functional.h",
+ "include/pybind11/iostream.h",
+ "include/pybind11/numpy.h",
+ "include/pybind11/operators.h",
+ "include/pybind11/options.h",
+ "include/pybind11/pybind11.h",
+ "include/pybind11/pytypes.h",
+ "include/pybind11/stl.h",
+ "include/pybind11/stl_bind.h",
+}
+
+detail_headers = {
+ "include/pybind11/detail/class.h",
+ "include/pybind11/detail/common.h",
+ "include/pybind11/detail/descr.h",
+ "include/pybind11/detail/init.h",
+ "include/pybind11/detail/internals.h",
+ "include/pybind11/detail/typeid.h",
+}
+
+cmake_files = {
+ "share/cmake/pybind11/FindPythonLibsNew.cmake",
+ "share/cmake/pybind11/pybind11Common.cmake",
+ "share/cmake/pybind11/pybind11Config.cmake",
+ "share/cmake/pybind11/pybind11ConfigVersion.cmake",
+ "share/cmake/pybind11/pybind11NewTools.cmake",
+ "share/cmake/pybind11/pybind11Targets.cmake",
+ "share/cmake/pybind11/pybind11Tools.cmake",
+}
+
+py_files = {
+ "__init__.py",
+ "__main__.py",
+ "_version.py",
+ "_version.pyi",
+ "commands.py",
+ "py.typed",
+ "setup_helpers.py",
+ "setup_helpers.pyi",
+}
+
+headers = main_headers | detail_headers
+src_files = headers | cmake_files
+all_files = src_files | py_files
+
+
+sdist_files = {
+ "pybind11",
+ "pybind11/include",
+ "pybind11/include/pybind11",
+ "pybind11/include/pybind11/detail",
+ "pybind11/share",
+ "pybind11/share/cmake",
+ "pybind11/share/cmake/pybind11",
+ "pyproject.toml",
+ "setup.cfg",
+ "setup.py",
+ "LICENSE",
+ "MANIFEST.in",
+ "README.rst",
+ "PKG-INFO",
+}
+
+local_sdist_files = {
+ ".egg-info",
+ ".egg-info/PKG-INFO",
+ ".egg-info/SOURCES.txt",
+ ".egg-info/dependency_links.txt",
+ ".egg-info/not-zip-safe",
+ ".egg-info/top_level.txt",
+}
+
+
+def test_build_sdist(monkeypatch, tmpdir):
+
+ monkeypatch.chdir(MAIN_DIR)
+
+ out = subprocess.check_output(
+ [
+ sys.executable,
+ "setup.py",
+ "sdist",
+ "--formats=tar",
+ "--dist-dir",
+ str(tmpdir),
+ ]
+ )
+ if hasattr(out, "decode"):
+ out = out.decode()
+
+ (sdist,) = tmpdir.visit("*.tar")
+
+ with tarfile.open(str(sdist)) as tar:
+ start = tar.getnames()[0] + "/"
+ version = start[9:-1]
+ simpler = set(n.split("/", 1)[-1] for n in tar.getnames()[1:])
+
+ with contextlib.closing(
+ tar.extractfile(tar.getmember(start + "setup.py"))
+ ) as f:
+ setup_py = f.read()
+
+ with contextlib.closing(
+ tar.extractfile(tar.getmember(start + "pyproject.toml"))
+ ) as f:
+ pyproject_toml = f.read()
+
+ files = set("pybind11/{}".format(n) for n in all_files)
+ files |= sdist_files
+ files |= set("pybind11{}".format(n) for n in local_sdist_files)
+ files.add("pybind11.egg-info/entry_points.txt")
+ files.add("pybind11.egg-info/requires.txt")
+ assert simpler == files
+
+ with open(os.path.join(MAIN_DIR, "tools", "setup_main.py.in"), "rb") as f:
+ contents = (
+ string.Template(f.read().decode())
+ .substitute(version=version, extra_cmd="")
+ .encode()
+ )
+ assert setup_py == contents
+
+ with open(os.path.join(MAIN_DIR, "tools", "pyproject.toml"), "rb") as f:
+ contents = f.read()
+ assert pyproject_toml == contents
+
+
+def test_build_global_dist(monkeypatch, tmpdir):
+
+ monkeypatch.chdir(MAIN_DIR)
+ monkeypatch.setenv("PYBIND11_GLOBAL_SDIST", "1")
+
+ out = subprocess.check_output(
+ [
+ sys.executable,
+ "setup.py",
+ "sdist",
+ "--formats=tar",
+ "--dist-dir",
+ str(tmpdir),
+ ]
+ )
+ if hasattr(out, "decode"):
+ out = out.decode()
+
+ (sdist,) = tmpdir.visit("*.tar")
+
+ with tarfile.open(str(sdist)) as tar:
+ start = tar.getnames()[0] + "/"
+ version = start[16:-1]
+ simpler = set(n.split("/", 1)[-1] for n in tar.getnames()[1:])
+
+ with contextlib.closing(
+ tar.extractfile(tar.getmember(start + "setup.py"))
+ ) as f:
+ setup_py = f.read()
+
+ with contextlib.closing(
+ tar.extractfile(tar.getmember(start + "pyproject.toml"))
+ ) as f:
+ pyproject_toml = f.read()
+
+ files = set("pybind11/{}".format(n) for n in all_files)
+ files |= sdist_files
+ files |= set("pybind11_global{}".format(n) for n in local_sdist_files)
+ assert simpler == files
+
+ with open(os.path.join(MAIN_DIR, "tools", "setup_global.py.in"), "rb") as f:
+ contents = (
+ string.Template(f.read().decode())
+ .substitute(version=version, extra_cmd="")
+ .encode()
+ )
+ assert setup_py == contents
+
+ with open(os.path.join(MAIN_DIR, "tools", "pyproject.toml"), "rb") as f:
+ contents = f.read()
+ assert pyproject_toml == contents
+
+
+def tests_build_wheel(monkeypatch, tmpdir):
+ monkeypatch.chdir(MAIN_DIR)
+
+ subprocess.check_output(
+ [sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)]
+ )
+
+ (wheel,) = tmpdir.visit("*.whl")
+
+ files = set("pybind11/{}".format(n) for n in all_files)
+ files |= {
+ "dist-info/LICENSE",
+ "dist-info/METADATA",
+ "dist-info/RECORD",
+ "dist-info/WHEEL",
+ "dist-info/entry_points.txt",
+ "dist-info/top_level.txt",
+ }
+
+ with zipfile.ZipFile(str(wheel)) as z:
+ names = z.namelist()
+
+ trimmed = set(n for n in names if "dist-info" not in n)
+ trimmed |= set(
+ "dist-info/{}".format(n.split("/", 1)[-1]) for n in names if "dist-info" in n
+ )
+ assert files == trimmed
+
+
+def tests_build_global_wheel(monkeypatch, tmpdir):
+ monkeypatch.chdir(MAIN_DIR)
+ monkeypatch.setenv("PYBIND11_GLOBAL_SDIST", "1")
+
+ subprocess.check_output(
+ [sys.executable, "-m", "pip", "wheel", ".", "-w", str(tmpdir)]
+ )
+
+ (wheel,) = tmpdir.visit("*.whl")
+
+ files = set("data/data/{}".format(n) for n in src_files)
+ files |= set("data/headers/{}".format(n[8:]) for n in headers)
+ files |= {
+ "dist-info/LICENSE",
+ "dist-info/METADATA",
+ "dist-info/WHEEL",
+ "dist-info/top_level.txt",
+ "dist-info/RECORD",
+ }
+
+ with zipfile.ZipFile(str(wheel)) as z:
+ names = z.namelist()
+
+ beginning = names[0].split("/", 1)[0].rsplit(".", 1)[0]
+ trimmed = set(n[len(beginning) + 1 :] for n in names)
+
+ assert files == trimmed
diff --git a/3rdparty/pybind11/tests/extra_setuptools/pytest.ini b/3rdparty/pybind11/tests/extra_setuptools/pytest.ini
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/3rdparty/pybind11/tests/extra_setuptools/pytest.ini
diff --git a/3rdparty/pybind11/tests/extra_setuptools/test_setuphelper.py b/3rdparty/pybind11/tests/extra_setuptools/test_setuphelper.py
new file mode 100644
index 00000000..0d8bd0e4
--- /dev/null
+++ b/3rdparty/pybind11/tests/extra_setuptools/test_setuphelper.py
@@ -0,0 +1,101 @@
+# -*- coding: utf-8 -*-
+import os
+import sys
+import subprocess
+from textwrap import dedent
+
+import pytest
+
+DIR = os.path.abspath(os.path.dirname(__file__))
+MAIN_DIR = os.path.dirname(os.path.dirname(DIR))
+
+
+@pytest.mark.parametrize("parallel", [False, True])
+@pytest.mark.parametrize("std", [11, 0])
+def test_simple_setup_py(monkeypatch, tmpdir, parallel, std):
+ monkeypatch.chdir(tmpdir)
+ monkeypatch.syspath_prepend(MAIN_DIR)
+
+ (tmpdir / "setup.py").write_text(
+ dedent(
+ u"""\
+ import sys
+ sys.path.append({MAIN_DIR!r})
+
+ from setuptools import setup, Extension
+ from pybind11.setup_helpers import build_ext, Pybind11Extension
+
+ std = {std}
+
+ ext_modules = [
+ Pybind11Extension(
+ "simple_setup",
+ sorted(["main.cpp"]),
+ cxx_std=std,
+ ),
+ ]
+
+ cmdclass = dict()
+ if std == 0:
+ cmdclass["build_ext"] = build_ext
+
+
+ parallel = {parallel}
+ if parallel:
+ from pybind11.setup_helpers import ParallelCompile
+ ParallelCompile().install()
+
+ setup(
+ name="simple_setup_package",
+ cmdclass=cmdclass,
+ ext_modules=ext_modules,
+ )
+ """
+ ).format(MAIN_DIR=MAIN_DIR, std=std, parallel=parallel),
+ encoding="ascii",
+ )
+
+ (tmpdir / "main.cpp").write_text(
+ dedent(
+ u"""\
+ #include <pybind11/pybind11.h>
+
+ int f(int x) {
+ return x * 3;
+ }
+ PYBIND11_MODULE(simple_setup, m) {
+ m.def("f", &f);
+ }
+ """
+ ),
+ encoding="ascii",
+ )
+
+ subprocess.check_call(
+ [sys.executable, "setup.py", "build_ext", "--inplace"],
+ stdout=sys.stdout,
+ stderr=sys.stderr,
+ )
+
+ # Debug helper printout, normally hidden
+ for item in tmpdir.listdir():
+ print(item.basename)
+
+ assert (
+ len([f for f in tmpdir.listdir() if f.basename.startswith("simple_setup")]) == 1
+ )
+ assert len(list(tmpdir.listdir())) == 4 # two files + output + build_dir
+
+ (tmpdir / "test.py").write_text(
+ dedent(
+ u"""\
+ import simple_setup
+ assert simple_setup.f(3) == 9
+ """
+ ),
+ encoding="ascii",
+ )
+
+ subprocess.check_call(
+ [sys.executable, "test.py"], stdout=sys.stdout, stderr=sys.stderr
+ )
diff --git a/3rdparty/pybind11/tests/local_bindings.h b/3rdparty/pybind11/tests/local_bindings.h
index b6afb808..22537b13 100644
--- a/3rdparty/pybind11/tests/local_bindings.h
+++ b/3rdparty/pybind11/tests/local_bindings.h
@@ -58,7 +58,7 @@ public:
std::string name_;
const std::string &name() { return name_; }
};
-}
+} // namespace pets
struct MixGL { int i; MixGL(int i) : i{i} {} };
struct MixGL2 { int i; MixGL2(int i) : i{i} {} };
diff --git a/3rdparty/pybind11/tests/pybind11_tests.cpp b/3rdparty/pybind11/tests/pybind11_tests.cpp
index bc7d2c3e..439cd401 100644
--- a/3rdparty/pybind11/tests/pybind11_tests.cpp
+++ b/3rdparty/pybind11/tests/pybind11_tests.cpp
@@ -26,23 +26,23 @@ productively.
Instead, see the "How can I reduce the build time?" question in the "Frequently asked questions"
section of the documentation for good practice on splitting binding code over multiple files.
*/
-std::list<std::function<void(py::module &)>> &initializers() {
- static std::list<std::function<void(py::module &)>> inits;
+std::list<std::function<void(py::module_ &)>> &initializers() {
+ static std::list<std::function<void(py::module_ &)>> inits;
return inits;
}
test_initializer::test_initializer(Initializer init) {
- initializers().push_back(init);
+ initializers().emplace_back(init);
}
test_initializer::test_initializer(const char *submodule_name, Initializer init) {
- initializers().push_back([=](py::module &parent) {
+ initializers().emplace_back([=](py::module_ &parent) {
auto m = parent.def_submodule(submodule_name);
init(m);
});
}
-void bind_ConstructorStats(py::module &m) {
+void bind_ConstructorStats(py::module_ &m) {
py::class_<ConstructorStats>(m, "ConstructorStats")
.def("alive", &ConstructorStats::alive)
.def("values", &ConstructorStats::values)
@@ -88,6 +88,4 @@ PYBIND11_MODULE(pybind11_tests, m) {
for (const auto &initializer : initializers())
initializer(m);
-
- if (!py::hasattr(m, "have_eigen")) m.attr("have_eigen") = false;
}
diff --git a/3rdparty/pybind11/tests/pybind11_tests.h b/3rdparty/pybind11/tests/pybind11_tests.h
index 90963a5d..4ff56c07 100644
--- a/3rdparty/pybind11/tests/pybind11_tests.h
+++ b/3rdparty/pybind11/tests/pybind11_tests.h
@@ -10,7 +10,7 @@ namespace py = pybind11;
using namespace pybind11::literals;
class test_initializer {
- using Initializer = void (*)(py::module &);
+ using Initializer = void (*)(py::module_ &);
public:
test_initializer(Initializer init);
@@ -18,9 +18,9 @@ public:
};
#define TEST_SUBMODULE(name, variable) \
- void test_submodule_##name(py::module &); \
+ void test_submodule_##name(py::module_ &); \
test_initializer name(#name, test_submodule_##name); \
- void test_submodule_##name(py::module &variable)
+ void test_submodule_##name(py::module_ &variable)
/// Dummy type which is not exported anywhere -- something to trigger a conversion error
@@ -50,16 +50,22 @@ public:
IncType &operator=(IncType &&) = delete;
};
+/// A simple union for basic testing
+union IntFloat {
+ int i;
+ float f;
+};
+
/// Custom cast-only type that casts to a string "rvalue" or "lvalue" depending on the cast context.
/// Used to test recursive casters (e.g. std::tuple, stl containers).
struct RValueCaster {};
-NAMESPACE_BEGIN(pybind11)
-NAMESPACE_BEGIN(detail)
+PYBIND11_NAMESPACE_BEGIN(pybind11)
+PYBIND11_NAMESPACE_BEGIN(detail)
template<> class type_caster<RValueCaster> {
public:
PYBIND11_TYPE_CASTER(RValueCaster, _("RValueCaster"));
static handle cast(RValueCaster &&, return_value_policy, handle) { return py::str("rvalue").release(); }
static handle cast(const RValueCaster &, return_value_policy, handle) { return py::str("lvalue").release(); }
};
-NAMESPACE_END(detail)
-NAMESPACE_END(pybind11)
+PYBIND11_NAMESPACE_END(detail)
+PYBIND11_NAMESPACE_END(pybind11)
diff --git a/3rdparty/pybind11/tests/pytest.ini b/3rdparty/pybind11/tests/pytest.ini
index f209964a..c47cbe9c 100644
--- a/3rdparty/pybind11/tests/pytest.ini
+++ b/3rdparty/pybind11/tests/pytest.ini
@@ -1,11 +1,14 @@
[pytest]
-minversion = 3.0
-norecursedirs = test_cmake_build test_embed
+minversion = 3.1
+norecursedirs = test_* extra_*
+xfail_strict = True
addopts =
# show summary of skipped tests
-rs
# capture only Python print and C++ py::print, but not C output (low-level Python errors)
--capture=sys
+ # enable all warnings
+ -Wa
filterwarnings =
# make warnings into errors but ignore certain third-party extension issues
error
diff --git a/3rdparty/pybind11/tests/requirements.txt b/3rdparty/pybind11/tests/requirements.txt
new file mode 100644
index 00000000..80ed6171
--- /dev/null
+++ b/3rdparty/pybind11/tests/requirements.txt
@@ -0,0 +1,8 @@
+--extra-index-url https://antocuni.github.io/pypy-wheels/manylinux2010/
+numpy==1.16.6; python_version<"3.6" and sys_platform!="win32"
+numpy==1.18.0; platform_python_implementation=="PyPy" and sys_platform=="darwin" and python_version>="3.6"
+numpy==1.19.3; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.6" and python_version<"3.10"
+pytest==4.6.9; python_version<"3.5"
+pytest==5.4.3; python_version>="3.5"
+scipy==1.2.3; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version<"3.6"
+scipy==1.5.2; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.6" and python_version<"3.9"
diff --git a/3rdparty/pybind11/tests/test_async.cpp b/3rdparty/pybind11/tests/test_async.cpp
index f0ad0d53..e6e01d72 100644
--- a/3rdparty/pybind11/tests/test_async.cpp
+++ b/3rdparty/pybind11/tests/test_async.cpp
@@ -18,7 +18,7 @@ TEST_SUBMODULE(async_module, m) {
.def(py::init<>())
.def("__await__", [](const SupportsAsync& self) -> py::object {
static_cast<void>(self);
- py::object loop = py::module::import("asyncio.events").attr("get_event_loop")();
+ py::object loop = py::module_::import("asyncio.events").attr("get_event_loop")();
py::object f = loop.attr("create_future")();
f.attr("set_result")(5);
return f.attr("__await__")();
diff --git a/3rdparty/pybind11/tests/test_async.py b/3rdparty/pybind11/tests/test_async.py
index e1c959d6..df4489c4 100644
--- a/3rdparty/pybind11/tests/test_async.py
+++ b/3rdparty/pybind11/tests/test_async.py
@@ -1,6 +1,8 @@
-import asyncio
+# -*- coding: utf-8 -*-
import pytest
-from pybind11_tests import async_module as m
+
+asyncio = pytest.importorskip("asyncio")
+m = pytest.importorskip("pybind11_tests.async_module")
@pytest.fixture
diff --git a/3rdparty/pybind11/tests/test_buffers.cpp b/3rdparty/pybind11/tests/test_buffers.cpp
index 1bc67ff7..46eabf39 100644
--- a/3rdparty/pybind11/tests/test_buffers.cpp
+++ b/3rdparty/pybind11/tests/test_buffers.cpp
@@ -9,12 +9,13 @@
#include "pybind11_tests.h"
#include "constructor_stats.h"
+#include <pybind11/stl.h>
TEST_SUBMODULE(buffers, m) {
// test_from_python / test_to_python:
class Matrix {
public:
- Matrix(ssize_t rows, ssize_t cols) : m_rows(rows), m_cols(cols) {
+ Matrix(py::ssize_t rows, py::ssize_t cols) : m_rows(rows), m_cols(cols) {
print_created(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
m_data = new float[(size_t) (rows*cols)];
memset(m_data, 0, sizeof(float) * (size_t) (rows * cols));
@@ -58,25 +59,25 @@ TEST_SUBMODULE(buffers, m) {
return *this;
}
- float operator()(ssize_t i, ssize_t j) const {
+ float operator()(py::ssize_t i, py::ssize_t j) const {
return m_data[(size_t) (i*m_cols + j)];
}
- float &operator()(ssize_t i, ssize_t j) {
+ float &operator()(py::ssize_t i, py::ssize_t j) {
return m_data[(size_t) (i*m_cols + j)];
}
float *data() { return m_data; }
- ssize_t rows() const { return m_rows; }
- ssize_t cols() const { return m_cols; }
+ py::ssize_t rows() const { return m_rows; }
+ py::ssize_t cols() const { return m_cols; }
private:
- ssize_t m_rows;
- ssize_t m_cols;
+ py::ssize_t m_rows;
+ py::ssize_t m_cols;
float *m_data;
};
py::class_<Matrix>(m, "Matrix", py::buffer_protocol())
- .def(py::init<ssize_t, ssize_t>())
+ .def(py::init<py::ssize_t, py::ssize_t>())
/// Construct from a buffer
.def(py::init([](py::buffer const b) {
py::buffer_info info = b.request();
@@ -92,12 +93,12 @@ TEST_SUBMODULE(buffers, m) {
.def("cols", &Matrix::cols)
/// Bare bones interface
- .def("__getitem__", [](const Matrix &m, std::pair<ssize_t, ssize_t> i) {
+ .def("__getitem__", [](const Matrix &m, std::pair<py::ssize_t, py::ssize_t> i) {
if (i.first >= m.rows() || i.second >= m.cols())
throw py::index_error();
return m(i.first, i.second);
})
- .def("__setitem__", [](Matrix &m, std::pair<ssize_t, ssize_t> i, float v) {
+ .def("__setitem__", [](Matrix &m, std::pair<py::ssize_t, py::ssize_t> i, float v) {
if (i.first >= m.rows() || i.second >= m.cols())
throw py::index_error();
m(i.first, i.second) = v;
@@ -117,11 +118,11 @@ TEST_SUBMODULE(buffers, m) {
// test_inherited_protocol
class SquareMatrix : public Matrix {
public:
- SquareMatrix(ssize_t n) : Matrix(n, n) { }
+ SquareMatrix(py::ssize_t n) : Matrix(n, n) { }
};
// Derived classes inherit the buffer protocol and the buffer access function
py::class_<SquareMatrix, Matrix>(m, "SquareMatrix")
- .def(py::init<ssize_t>());
+ .def(py::init<py::ssize_t>());
// test_pointer_to_member_fn
@@ -192,4 +193,22 @@ TEST_SUBMODULE(buffers, m) {
.def_readwrite("readonly", &BufferReadOnlySelect::readonly)
.def_buffer(&BufferReadOnlySelect::get_buffer_info);
+ // Expose buffer_info for testing.
+ py::class_<py::buffer_info>(m, "buffer_info")
+ .def(py::init<>())
+ .def_readonly("itemsize", &py::buffer_info::itemsize)
+ .def_readonly("size", &py::buffer_info::size)
+ .def_readonly("format", &py::buffer_info::format)
+ .def_readonly("ndim", &py::buffer_info::ndim)
+ .def_readonly("shape", &py::buffer_info::shape)
+ .def_readonly("strides", &py::buffer_info::strides)
+ .def_readonly("readonly", &py::buffer_info::readonly)
+ .def("__repr__", [](py::handle self) {
+ return py::str("itemsize={0.itemsize!r}, size={0.size!r}, format={0.format!r}, ndim={0.ndim!r}, shape={0.shape!r}, strides={0.strides!r}, readonly={0.readonly!r}").format(self);
+ })
+ ;
+
+ m.def("get_buffer_info", [](py::buffer buffer) {
+ return buffer.request();
+ });
}
diff --git a/3rdparty/pybind11/tests/test_buffers.py b/3rdparty/pybind11/tests/test_buffers.py
index bf7aaed7..f0f37084 100644
--- a/3rdparty/pybind11/tests/test_buffers.py
+++ b/3rdparty/pybind11/tests/test_buffers.py
@@ -1,18 +1,16 @@
+# -*- coding: utf-8 -*-
import io
import struct
-import sys
+import ctypes
import pytest
+import env # noqa: F401
+
from pybind11_tests import buffers as m
from pybind11_tests import ConstructorStats
-PY3 = sys.version_info[0] >= 3
-
-pytestmark = pytest.requires_numpy
-
-with pytest.suppress(ImportError):
- import numpy as np
+np = pytest.importorskip("numpy")
def test_from_python():
@@ -38,9 +36,7 @@ def test_from_python():
assert cstats.move_assignments == 0
-# PyPy: Memory leak in the "np.array(m, copy=False)" call
-# https://bitbucket.org/pypy/pypy/issues/2444
-@pytest.unsupported_on_pypy
+# https://foss.heptapod.net/pypy/pypy/-/issues/2444
def test_to_python():
mat = m.Matrix(5, 4)
assert memoryview(mat).shape == (5, 4)
@@ -50,8 +46,8 @@ def test_to_python():
mat[3, 2] = 7.0
assert mat[2, 3] == 4
assert mat[3, 2] == 7
- assert struct.unpack_from('f', mat, (3 * 4 + 2) * 4) == (7, )
- assert struct.unpack_from('f', mat, (2 * 4 + 3) * 4) == (4, )
+ assert struct.unpack_from("f", mat, (3 * 4 + 2) * 4) == (7,)
+ assert struct.unpack_from("f", mat, (2 * 4 + 3) * 4) == (4,)
mat2 = np.array(mat, copy=False)
assert mat2.shape == (5, 4)
@@ -75,7 +71,6 @@ def test_to_python():
assert cstats.move_assignments == 0
-@pytest.unsupported_on_pypy
def test_inherited_protocol():
"""SquareMatrix is derived from Matrix and inherits the buffer protocol"""
@@ -84,35 +79,84 @@ def test_inherited_protocol():
assert np.asarray(matrix).shape == (5, 5)
-@pytest.unsupported_on_pypy
def test_pointer_to_member_fn():
for cls in [m.Buffer, m.ConstBuffer, m.DerivedBuffer]:
buf = cls()
buf.value = 0x12345678
- value = struct.unpack('i', bytearray(buf))[0]
+ value = struct.unpack("i", bytearray(buf))[0]
assert value == 0x12345678
-@pytest.unsupported_on_pypy
def test_readonly_buffer():
buf = m.BufferReadOnly(0x64)
view = memoryview(buf)
- assert view[0] == 0x64 if PY3 else b'd'
+ assert view[0] == b"d" if env.PY2 else 0x64
assert view.readonly
-@pytest.unsupported_on_pypy
def test_selective_readonly_buffer():
buf = m.BufferReadOnlySelect()
- memoryview(buf)[0] = 0x64 if PY3 else b'd'
+ memoryview(buf)[0] = b"d" if env.PY2 else 0x64
assert buf.value == 0x64
- io.BytesIO(b'A').readinto(buf)
- assert buf.value == ord(b'A')
+ io.BytesIO(b"A").readinto(buf)
+ assert buf.value == ord(b"A")
buf.readonly = True
with pytest.raises(TypeError):
- memoryview(buf)[0] = 0 if PY3 else b'\0'
+ memoryview(buf)[0] = b"\0" if env.PY2 else 0
with pytest.raises(TypeError):
- io.BytesIO(b'1').readinto(buf)
+ io.BytesIO(b"1").readinto(buf)
+
+
+def test_ctypes_array_1d():
+ char1d = (ctypes.c_char * 10)()
+ int1d = (ctypes.c_int * 15)()
+ long1d = (ctypes.c_long * 7)()
+
+ for carray in (char1d, int1d, long1d):
+ info = m.get_buffer_info(carray)
+ assert info.itemsize == ctypes.sizeof(carray._type_)
+ assert info.size == len(carray)
+ assert info.ndim == 1
+ assert info.shape == [info.size]
+ assert info.strides == [info.itemsize]
+ assert not info.readonly
+
+
+def test_ctypes_array_2d():
+ char2d = ((ctypes.c_char * 10) * 4)()
+ int2d = ((ctypes.c_int * 15) * 3)()
+ long2d = ((ctypes.c_long * 7) * 2)()
+
+ for carray in (char2d, int2d, long2d):
+ info = m.get_buffer_info(carray)
+ assert info.itemsize == ctypes.sizeof(carray[0]._type_)
+ assert info.size == len(carray) * len(carray[0])
+ assert info.ndim == 2
+ assert info.shape == [len(carray), len(carray[0])]
+ assert info.strides == [info.itemsize * len(carray[0]), info.itemsize]
+ assert not info.readonly
+
+
+@pytest.mark.skipif(
+ "env.PYPY and env.PY2", reason="PyPy2 bytes buffer not reported as readonly"
+)
+def test_ctypes_from_buffer():
+ test_pystr = b"0123456789"
+ for pyarray in (test_pystr, bytearray(test_pystr)):
+ pyinfo = m.get_buffer_info(pyarray)
+
+ if pyinfo.readonly:
+ cbytes = (ctypes.c_char * len(pyarray)).from_buffer_copy(pyarray)
+ cinfo = m.get_buffer_info(cbytes)
+ else:
+ cbytes = (ctypes.c_char * len(pyarray)).from_buffer(pyarray)
+ cinfo = m.get_buffer_info(cbytes)
+
+ assert cinfo.size == pyinfo.size
+ assert cinfo.ndim == pyinfo.ndim
+ assert cinfo.shape == pyinfo.shape
+ assert cinfo.strides == pyinfo.strides
+ assert not cinfo.readonly
diff --git a/3rdparty/pybind11/tests/test_builtin_casters.cpp b/3rdparty/pybind11/tests/test_builtin_casters.cpp
index acb24469..acc9f8fb 100644
--- a/3rdparty/pybind11/tests/test_builtin_casters.cpp
+++ b/3rdparty/pybind11/tests/test_builtin_casters.cpp
@@ -117,12 +117,16 @@ TEST_SUBMODULE(builtin_casters, m) {
return std::make_pair(RValueCaster{}, std::make_tuple(RValueCaster{}, std::make_pair(RValueCaster{}, RValueCaster{}))); });
m.def("lvalue_nested", []() -> const decltype(lvnested) & { return lvnested; });
+ static std::pair<int, std::string> int_string_pair{2, "items"};
+ m.def("int_string_pair", []() { return &int_string_pair; });
+
// test_builtins_cast_return_none
m.def("return_none_string", []() -> std::string * { return nullptr; });
m.def("return_none_char", []() -> const char * { return nullptr; });
m.def("return_none_bool", []() -> bool * { return nullptr; });
m.def("return_none_int", []() -> int * { return nullptr; });
m.def("return_none_float", []() -> float * { return nullptr; });
+ m.def("return_none_pair", []() -> std::pair<int,int> * { return nullptr; });
// test_none_deferred
m.def("defer_none_cstring", [](char *) { return false; });
diff --git a/3rdparty/pybind11/tests/test_builtin_casters.py b/3rdparty/pybind11/tests/test_builtin_casters.py
index 91422588..bd7996b6 100644
--- a/3rdparty/pybind11/tests/test_builtin_casters.py
+++ b/3rdparty/pybind11/tests/test_builtin_casters.py
@@ -1,6 +1,8 @@
-# Python < 3 needs this: coding=utf-8
+# -*- coding: utf-8 -*-
import pytest
+import env # noqa: F401
+
from pybind11_tests import builtin_casters as m
from pybind11_tests import UserType, IncType
@@ -35,79 +37,85 @@ def test_unicode_conversion():
with pytest.raises(UnicodeDecodeError):
m.bad_utf8_u8string()
- assert m.u8_Z() == 'Z'
- assert m.u8_eacute() == u'é'
- assert m.u16_ibang() == u'‽'
- assert m.u32_mathbfA() == u'𝐀'
- assert m.wchar_heart() == u'♥'
+ assert m.u8_Z() == "Z"
+ assert m.u8_eacute() == u"é"
+ assert m.u16_ibang() == u"‽"
+ assert m.u32_mathbfA() == u"𝐀"
+ assert m.wchar_heart() == u"♥"
if hasattr(m, "has_u8string"):
- assert m.u8_char8_Z() == 'Z'
+ assert m.u8_char8_Z() == "Z"
def test_single_char_arguments():
"""Tests failures for passing invalid inputs to char-accepting functions"""
+
def toobig_message(r):
return "Character code point not in range({0:#x})".format(r)
+
toolong_message = "Expected a character, but multi-character string found"
- assert m.ord_char(u'a') == 0x61 # simple ASCII
- assert m.ord_char_lv(u'b') == 0x62
- assert m.ord_char(u'é') == 0xE9 # requires 2 bytes in utf-8, but can be stuffed in a char
+ assert m.ord_char(u"a") == 0x61 # simple ASCII
+ assert m.ord_char_lv(u"b") == 0x62
+ assert (
+ m.ord_char(u"é") == 0xE9
+ ) # requires 2 bytes in utf-8, but can be stuffed in a char
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char(u'Ā') == 0x100 # requires 2 bytes, doesn't fit in a char
+ assert m.ord_char(u"Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
assert str(excinfo.value) == toobig_message(0x100)
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char(u'ab')
+ assert m.ord_char(u"ab")
assert str(excinfo.value) == toolong_message
- assert m.ord_char16(u'a') == 0x61
- assert m.ord_char16(u'é') == 0xE9
- assert m.ord_char16_lv(u'ê') == 0xEA
- assert m.ord_char16(u'Ā') == 0x100
- assert m.ord_char16(u'‽') == 0x203d
- assert m.ord_char16(u'♥') == 0x2665
- assert m.ord_char16_lv(u'♡') == 0x2661
+ assert m.ord_char16(u"a") == 0x61
+ assert m.ord_char16(u"é") == 0xE9
+ assert m.ord_char16_lv(u"ê") == 0xEA
+ assert m.ord_char16(u"Ā") == 0x100
+ assert m.ord_char16(u"‽") == 0x203D
+ assert m.ord_char16(u"♥") == 0x2665
+ assert m.ord_char16_lv(u"♡") == 0x2661
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char16(u'🎂') == 0x1F382 # requires surrogate pair
+ assert m.ord_char16(u"🎂") == 0x1F382 # requires surrogate pair
assert str(excinfo.value) == toobig_message(0x10000)
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char16(u'aa')
+ assert m.ord_char16(u"aa")
assert str(excinfo.value) == toolong_message
- assert m.ord_char32(u'a') == 0x61
- assert m.ord_char32(u'é') == 0xE9
- assert m.ord_char32(u'Ā') == 0x100
- assert m.ord_char32(u'‽') == 0x203d
- assert m.ord_char32(u'♥') == 0x2665
- assert m.ord_char32(u'🎂') == 0x1F382
+ assert m.ord_char32(u"a") == 0x61
+ assert m.ord_char32(u"é") == 0xE9
+ assert m.ord_char32(u"Ā") == 0x100
+ assert m.ord_char32(u"‽") == 0x203D
+ assert m.ord_char32(u"♥") == 0x2665
+ assert m.ord_char32(u"🎂") == 0x1F382
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char32(u'aa')
+ assert m.ord_char32(u"aa")
assert str(excinfo.value) == toolong_message
- assert m.ord_wchar(u'a') == 0x61
- assert m.ord_wchar(u'é') == 0xE9
- assert m.ord_wchar(u'Ā') == 0x100
- assert m.ord_wchar(u'‽') == 0x203d
- assert m.ord_wchar(u'♥') == 0x2665
+ assert m.ord_wchar(u"a") == 0x61
+ assert m.ord_wchar(u"é") == 0xE9
+ assert m.ord_wchar(u"Ā") == 0x100
+ assert m.ord_wchar(u"‽") == 0x203D
+ assert m.ord_wchar(u"♥") == 0x2665
if m.wchar_size == 2:
with pytest.raises(ValueError) as excinfo:
- assert m.ord_wchar(u'🎂') == 0x1F382 # requires surrogate pair
+ assert m.ord_wchar(u"🎂") == 0x1F382 # requires surrogate pair
assert str(excinfo.value) == toobig_message(0x10000)
else:
- assert m.ord_wchar(u'🎂') == 0x1F382
+ assert m.ord_wchar(u"🎂") == 0x1F382
with pytest.raises(ValueError) as excinfo:
- assert m.ord_wchar(u'aa')
+ assert m.ord_wchar(u"aa")
assert str(excinfo.value) == toolong_message
if hasattr(m, "has_u8string"):
- assert m.ord_char8(u'a') == 0x61 # simple ASCII
- assert m.ord_char8_lv(u'b') == 0x62
- assert m.ord_char8(u'é') == 0xE9 # requires 2 bytes in utf-8, but can be stuffed in a char
+ assert m.ord_char8(u"a") == 0x61 # simple ASCII
+ assert m.ord_char8_lv(u"b") == 0x62
+ assert (
+ m.ord_char8(u"é") == 0xE9
+ ) # requires 2 bytes in utf-8, but can be stuffed in a char
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char8(u'Ā') == 0x100 # requires 2 bytes, doesn't fit in a char
+ assert m.ord_char8(u"Ā") == 0x100 # requires 2 bytes, doesn't fit in a char
assert str(excinfo.value) == toobig_message(0x100)
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char8(u'ab')
+ assert m.ord_char8(u"ab")
assert str(excinfo.value) == toolong_message
@@ -115,88 +123,108 @@ def test_bytes_to_string():
"""Tests the ability to pass bytes to C++ string-accepting functions. Note that this is
one-way: the only way to return bytes to Python is via the pybind11::bytes class."""
# Issue #816
- import sys
- byte = bytes if sys.version_info[0] < 3 else str
- assert m.strlen(byte("hi")) == 2
- assert m.string_length(byte("world")) == 5
- assert m.string_length(byte("a\x00b")) == 3
- assert m.strlen(byte("a\x00b")) == 1 # C-string limitation
+ def to_bytes(s):
+ b = s if env.PY2 else s.encode("utf8")
+ assert isinstance(b, bytes)
+ return b
+
+ assert m.strlen(to_bytes("hi")) == 2
+ assert m.string_length(to_bytes("world")) == 5
+ assert m.string_length(to_bytes("a\x00b")) == 3
+ assert m.strlen(to_bytes("a\x00b")) == 1 # C-string limitation
# passing in a utf8 encoded string should work
- assert m.string_length(u'💩'.encode("utf8")) == 4
+ assert m.string_length(u"💩".encode("utf8")) == 4
@pytest.mark.skipif(not hasattr(m, "has_string_view"), reason="no <string_view>")
def test_string_view(capture):
"""Tests support for C++17 string_view arguments and return values"""
assert m.string_view_chars("Hi") == [72, 105]
- assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xf0, 0x9f, 0x8e, 0x82]
- assert m.string_view16_chars("Hi 🎂") == [72, 105, 32, 0xd83c, 0xdf82]
- assert m.string_view32_chars("Hi 🎂") == [72, 105, 32, 127874]
+ assert m.string_view_chars("Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
+ assert m.string_view16_chars(u"Hi 🎂") == [72, 105, 32, 0xD83C, 0xDF82]
+ assert m.string_view32_chars(u"Hi 🎂") == [72, 105, 32, 127874]
if hasattr(m, "has_u8string"):
assert m.string_view8_chars("Hi") == [72, 105]
- assert m.string_view8_chars("Hi 🎂") == [72, 105, 32, 0xf0, 0x9f, 0x8e, 0x82]
+ assert m.string_view8_chars(u"Hi 🎂") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
- assert m.string_view_return() == "utf8 secret 🎂"
- assert m.string_view16_return() == "utf16 secret 🎂"
- assert m.string_view32_return() == "utf32 secret 🎂"
+ assert m.string_view_return() == u"utf8 secret 🎂"
+ assert m.string_view16_return() == u"utf16 secret 🎂"
+ assert m.string_view32_return() == u"utf32 secret 🎂"
if hasattr(m, "has_u8string"):
- assert m.string_view8_return() == "utf8 secret 🎂"
+ assert m.string_view8_return() == u"utf8 secret 🎂"
with capture:
m.string_view_print("Hi")
m.string_view_print("utf8 🎂")
- m.string_view16_print("utf16 🎂")
- m.string_view32_print("utf32 🎂")
- assert capture == """
+ m.string_view16_print(u"utf16 🎂")
+ m.string_view32_print(u"utf32 🎂")
+ assert (
+ capture
+ == u"""
Hi 2
utf8 🎂 9
utf16 🎂 8
utf32 🎂 7
"""
+ )
if hasattr(m, "has_u8string"):
with capture:
m.string_view8_print("Hi")
- m.string_view8_print("utf8 🎂")
- assert capture == """
+ m.string_view8_print(u"utf8 🎂")
+ assert (
+ capture
+ == u"""
Hi 2
utf8 🎂 9
"""
+ )
with capture:
m.string_view_print("Hi, ascii")
m.string_view_print("Hi, utf8 🎂")
- m.string_view16_print("Hi, utf16 🎂")
- m.string_view32_print("Hi, utf32 🎂")
- assert capture == """
+ m.string_view16_print(u"Hi, utf16 🎂")
+ m.string_view32_print(u"Hi, utf32 🎂")
+ assert (
+ capture
+ == u"""
Hi, ascii 9
Hi, utf8 🎂 13
Hi, utf16 🎂 12
Hi, utf32 🎂 11
"""
+ )
if hasattr(m, "has_u8string"):
with capture:
m.string_view8_print("Hi, ascii")
- m.string_view8_print("Hi, utf8 🎂")
- assert capture == """
+ m.string_view8_print(u"Hi, utf8 🎂")
+ assert (
+ capture
+ == u"""
Hi, ascii 9
Hi, utf8 🎂 13
"""
+ )
def test_integer_casting():
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
- import sys
assert m.i32_str(-1) == "-1"
assert m.i64_str(-1) == "-1"
assert m.i32_str(2000000000) == "2000000000"
assert m.u32_str(2000000000) == "2000000000"
- if sys.version_info < (3,):
+ if env.PY2:
assert m.i32_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
assert m.i64_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
- assert m.i64_str(long(-999999999999)) == "-999999999999" # noqa: F821 undefined name
- assert m.u64_str(long(999999999999)) == "999999999999" # noqa: F821 undefined name 'long'
+ assert (
+ m.i64_str(long(-999999999999)) # noqa: F821 undefined name 'long'
+ == "-999999999999"
+ )
+ assert (
+ m.u64_str(long(999999999999)) # noqa: F821 undefined name 'long'
+ == "999999999999"
+ )
else:
assert m.i64_str(-999999999999) == "-999999999999"
assert m.u64_str(999999999999) == "999999999999"
@@ -214,7 +242,7 @@ def test_integer_casting():
m.i32_str(3000000000)
assert "incompatible function arguments" in str(excinfo.value)
- if sys.version_info < (3,):
+ if env.PY2:
with pytest.raises(TypeError) as excinfo:
m.u32_str(long(-1)) # noqa: F821 undefined name 'long'
assert "incompatible function arguments" in str(excinfo.value)
@@ -232,16 +260,22 @@ def test_tuple(doc):
assert m.tuple_passthrough([True, "test", 5]) == (5, "test", True)
assert m.empty_tuple() == ()
- assert doc(m.pair_passthrough) == """
+ assert (
+ doc(m.pair_passthrough)
+ == """
pair_passthrough(arg0: Tuple[bool, str]) -> Tuple[str, bool]
Return a pair in reversed order
"""
- assert doc(m.tuple_passthrough) == """
+ )
+ assert (
+ doc(m.tuple_passthrough)
+ == """
tuple_passthrough(arg0: Tuple[bool, str, int]) -> Tuple[int, str, bool]
Return a triple in reversed order
"""
+ )
assert m.rvalue_pair() == ("rvalue", "rvalue")
assert m.lvalue_pair() == ("lvalue", "lvalue")
@@ -250,6 +284,8 @@ def test_tuple(doc):
assert m.rvalue_nested() == ("rvalue", ("rvalue", ("rvalue", "rvalue")))
assert m.lvalue_nested() == ("lvalue", ("lvalue", ("lvalue", "lvalue")))
+ assert m.int_string_pair() == (2, "items")
+
def test_builtins_cast_return_none():
"""Casters produced with PYBIND11_TYPE_CASTER() should convert nullptr to None"""
@@ -258,6 +294,7 @@ def test_builtins_cast_return_none():
assert m.return_none_bool() is None
assert m.return_none_int() is None
assert m.return_none_float() is None
+ assert m.return_none_pair() is None
def test_none_deferred():
@@ -352,9 +389,9 @@ def test_bool_caster():
assert convert(A(False)) is False
-@pytest.requires_numpy
def test_numpy_bool():
- import numpy as np
+ np = pytest.importorskip("numpy")
+
convert, noconvert = m.bool_passthrough, m.bool_passthrough_noconvert
def cant_convert(v):
@@ -365,7 +402,7 @@ def test_numpy_bool():
assert convert(np.bool_(False)) is False
assert noconvert(np.bool_(True)) is True
assert noconvert(np.bool_(False)) is False
- cant_convert(np.zeros(2, dtype='int'))
+ cant_convert(np.zeros(2, dtype="int"))
def test_int_long():
@@ -375,7 +412,8 @@ def test_int_long():
long."""
import sys
- must_be_long = type(getattr(sys, 'maxint', 1) + 1)
+
+ must_be_long = type(getattr(sys, "maxint", 1) + 1)
assert isinstance(m.int_cast(), int)
assert isinstance(m.long_cast(), int)
assert isinstance(m.longlong_cast(), must_be_long)
diff --git a/3rdparty/pybind11/tests/test_call_policies.cpp b/3rdparty/pybind11/tests/test_call_policies.cpp
index fd245578..26c83f81 100644
--- a/3rdparty/pybind11/tests/test_call_policies.cpp
+++ b/3rdparty/pybind11/tests/test_call_policies.cpp
@@ -46,6 +46,7 @@ TEST_SUBMODULE(call_policies, m) {
class Parent {
public:
Parent() { py::print("Allocating parent."); }
+ Parent(const Parent& parent) = default;
~Parent() { py::print("Releasing parent."); }
void addChild(Child *) { }
Child *returnChild() { return new Child(); }
diff --git a/3rdparty/pybind11/tests/test_call_policies.py b/3rdparty/pybind11/tests/test_call_policies.py
index 7c835599..e0413d14 100644
--- a/3rdparty/pybind11/tests/test_call_policies.py
+++ b/3rdparty/pybind11/tests/test_call_policies.py
@@ -1,8 +1,13 @@
+# -*- coding: utf-8 -*-
import pytest
+
+import env # noqa: F401
+
from pybind11_tests import call_policies as m
from pybind11_tests import ConstructorStats
+@pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
def test_keep_alive_argument(capture):
n_inst = ConstructorStats.detail_reg_inst()
with capture:
@@ -11,10 +16,13 @@ def test_keep_alive_argument(capture):
with capture:
p.addChild(m.Child())
assert ConstructorStats.detail_reg_inst() == n_inst + 1
- assert capture == """
+ assert (
+ capture
+ == """
Allocating child.
Releasing child.
"""
+ )
with capture:
del p
assert ConstructorStats.detail_reg_inst() == n_inst
@@ -30,10 +38,13 @@ def test_keep_alive_argument(capture):
with capture:
del p
assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == """
+ assert (
+ capture
+ == """
Releasing parent.
Releasing child.
"""
+ )
def test_keep_alive_return_value(capture):
@@ -44,10 +55,13 @@ def test_keep_alive_return_value(capture):
with capture:
p.returnChild()
assert ConstructorStats.detail_reg_inst() == n_inst + 1
- assert capture == """
+ assert (
+ capture
+ == """
Allocating child.
Releasing child.
"""
+ )
with capture:
del p
assert ConstructorStats.detail_reg_inst() == n_inst
@@ -63,28 +77,34 @@ def test_keep_alive_return_value(capture):
with capture:
del p
assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == """
+ assert (
+ capture
+ == """
Releasing parent.
Releasing child.
"""
+ )
-# https://bitbucket.org/pypy/pypy/issues/2447
-@pytest.unsupported_on_pypy
+# https://foss.heptapod.net/pypy/pypy/-/issues/2447
+@pytest.mark.xfail("env.PYPY", reason="_PyObject_GetDictPtr is unimplemented")
def test_alive_gc(capture):
n_inst = ConstructorStats.detail_reg_inst()
p = m.ParentGC()
p.addChildKeepAlive(m.Child())
assert ConstructorStats.detail_reg_inst() == n_inst + 2
lst = [p]
- lst.append(lst) # creates a circular reference
+ lst.append(lst) # creates a circular reference
with capture:
del p, lst
assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == """
+ assert (
+ capture
+ == """
Releasing parent.
Releasing child.
"""
+ )
def test_alive_gc_derived(capture):
@@ -96,14 +116,17 @@ def test_alive_gc_derived(capture):
p.addChildKeepAlive(m.Child())
assert ConstructorStats.detail_reg_inst() == n_inst + 2
lst = [p]
- lst.append(lst) # creates a circular reference
+ lst.append(lst) # creates a circular reference
with capture:
del p, lst
assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == """
+ assert (
+ capture
+ == """
Releasing parent.
Releasing child.
"""
+ )
def test_alive_gc_multi_derived(capture):
@@ -118,15 +141,18 @@ def test_alive_gc_multi_derived(capture):
# +3 rather than +2 because Derived corresponds to two registered instances
assert ConstructorStats.detail_reg_inst() == n_inst + 3
lst = [p]
- lst.append(lst) # creates a circular reference
+ lst.append(lst) # creates a circular reference
with capture:
del p, lst
assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == """
+ assert (
+ capture
+ == """
Releasing parent.
Releasing child.
Releasing child.
"""
+ )
def test_return_none(capture):
@@ -162,17 +188,23 @@ def test_keep_alive_constructor(capture):
with capture:
p = m.Parent(m.Child())
assert ConstructorStats.detail_reg_inst() == n_inst + 2
- assert capture == """
+ assert (
+ capture
+ == """
Allocating child.
Allocating parent.
"""
+ )
with capture:
del p
assert ConstructorStats.detail_reg_inst() == n_inst
- assert capture == """
+ assert (
+ capture
+ == """
Releasing parent.
Releasing child.
"""
+ )
def test_call_guard():
diff --git a/3rdparty/pybind11/tests/test_callbacks.cpp b/3rdparty/pybind11/tests/test_callbacks.cpp
index 71b88c44..683dfb3e 100644
--- a/3rdparty/pybind11/tests/test_callbacks.cpp
+++ b/3rdparty/pybind11/tests/test_callbacks.cpp
@@ -117,7 +117,11 @@ TEST_SUBMODULE(callbacks, m) {
}
});
- class AbstractBase { public: virtual unsigned int func() = 0; };
+ class AbstractBase {
+ public:
+ virtual ~AbstractBase() = default;
+ virtual unsigned int func() = 0;
+ };
m.def("func_accepting_func_accepting_base", [](std::function<double(AbstractBase&)>) { });
struct MovableObject {
diff --git a/3rdparty/pybind11/tests/test_callbacks.py b/3rdparty/pybind11/tests/test_callbacks.py
index 6439c8e7..039b877c 100644
--- a/3rdparty/pybind11/tests/test_callbacks.py
+++ b/3rdparty/pybind11/tests/test_callbacks.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import callbacks as m
from threading import Thread
@@ -41,17 +42,19 @@ def test_bound_method_callback():
def test_keyword_args_and_generalized_unpacking():
-
def f(*args, **kwargs):
return args, kwargs
assert m.test_tuple_unpacking(f) == (("positional", 1, 2, 3, 4, 5, 6), {})
- assert m.test_dict_unpacking(f) == (("positional", 1), {"key": "value", "a": 1, "b": 2})
+ assert m.test_dict_unpacking(f) == (
+ ("positional", 1),
+ {"key": "value", "a": 1, "b": 2},
+ )
assert m.test_keyword_args(f) == ((), {"x": 10, "y": 20})
assert m.test_unpacking_and_keywords1(f) == ((1, 2), {"c": 3, "d": 4})
assert m.test_unpacking_and_keywords2(f) == (
("positional", 1, 2, 3, 4, 5),
- {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5}
+ {"key": "value", "a": 1, "b": 2, "c": 3, "d": 4, "e": 5},
)
with pytest.raises(TypeError) as excinfo:
@@ -82,12 +85,18 @@ def test_lambda_closure_cleanup():
def test_cpp_function_roundtrip():
"""Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""
- assert m.test_dummy_function(m.dummy_function) == "matches dummy_function: eval(1) = 2"
- assert (m.test_dummy_function(m.roundtrip(m.dummy_function)) ==
- "matches dummy_function: eval(1) = 2")
+ assert (
+ m.test_dummy_function(m.dummy_function) == "matches dummy_function: eval(1) = 2"
+ )
+ assert (
+ m.test_dummy_function(m.roundtrip(m.dummy_function))
+ == "matches dummy_function: eval(1) = 2"
+ )
assert m.roundtrip(None, expect_none=True) is None
- assert (m.test_dummy_function(lambda x: x + 2) ==
- "can't convert to function pointer: eval(1) = 3")
+ assert (
+ m.test_dummy_function(lambda x: x + 2)
+ == "can't convert to function pointer: eval(1) = 3"
+ )
with pytest.raises(TypeError) as excinfo:
m.test_dummy_function(m.dummy_function2)
@@ -95,8 +104,10 @@ def test_cpp_function_roundtrip():
with pytest.raises(TypeError) as excinfo:
m.test_dummy_function(lambda x, y: x + y)
- assert any(s in str(excinfo.value) for s in ("missing 1 required positional argument",
- "takes exactly 2 arguments"))
+ assert any(
+ s in str(excinfo.value)
+ for s in ("missing 1 required positional argument", "takes exactly 2 arguments")
+ )
def test_function_signatures(doc):
@@ -126,6 +137,7 @@ def test_async_callbacks():
m.test_async_callback(gen_f(), work)
# wait until work is done
from time import sleep
+
sleep(0.5)
assert sum(res) == sum([x + 3 for x in work])
diff --git a/3rdparty/pybind11/tests/test_chrono.cpp b/3rdparty/pybind11/tests/test_chrono.cpp
index 899d08d8..65370508 100644
--- a/3rdparty/pybind11/tests/test_chrono.cpp
+++ b/3rdparty/pybind11/tests/test_chrono.cpp
@@ -10,6 +10,25 @@
#include "pybind11_tests.h"
#include <pybind11/chrono.h>
+#include <chrono>
+
+struct different_resolutions {
+ using time_point_h = std::chrono::time_point<
+ std::chrono::system_clock, std::chrono::hours>;
+ using time_point_m = std::chrono::time_point<
+ std::chrono::system_clock, std::chrono::minutes>;
+ using time_point_s = std::chrono::time_point<
+ std::chrono::system_clock, std::chrono::seconds>;
+ using time_point_ms = std::chrono::time_point<
+ std::chrono::system_clock, std::chrono::milliseconds>;
+ using time_point_us = std::chrono::time_point<
+ std::chrono::system_clock, std::chrono::microseconds>;
+ time_point_h timestamp_h;
+ time_point_m timestamp_m;
+ time_point_s timestamp_s;
+ time_point_ms timestamp_ms;
+ time_point_us timestamp_us;
+};
TEST_SUBMODULE(chrono, m) {
using system_time = std::chrono::system_clock::time_point;
@@ -52,4 +71,14 @@ TEST_SUBMODULE(chrono, m) {
m.def("test_nano_timepoint", [](timestamp start, timespan delta) -> timestamp {
return start + delta;
});
+
+ // Test different resolutions
+ py::class_<different_resolutions>(m, "different_resolutions")
+ .def(py::init<>())
+ .def_readwrite("timestamp_h", &different_resolutions::timestamp_h)
+ .def_readwrite("timestamp_m", &different_resolutions::timestamp_m)
+ .def_readwrite("timestamp_s", &different_resolutions::timestamp_s)
+ .def_readwrite("timestamp_ms", &different_resolutions::timestamp_ms)
+ .def_readwrite("timestamp_us", &different_resolutions::timestamp_us)
+ ;
}
diff --git a/3rdparty/pybind11/tests/test_chrono.py b/3rdparty/pybind11/tests/test_chrono.py
index 55c95440..e9e24e08 100644
--- a/3rdparty/pybind11/tests/test_chrono.py
+++ b/3rdparty/pybind11/tests/test_chrono.py
@@ -1,10 +1,15 @@
+# -*- coding: utf-8 -*-
from pybind11_tests import chrono as m
import datetime
+import pytest
+
+import env # noqa: F401
def test_chrono_system_clock():
# Get the time from both c++ and datetime
+ date0 = datetime.datetime.today()
date1 = m.test_chrono1()
date2 = datetime.datetime.today()
@@ -12,16 +17,15 @@ def test_chrono_system_clock():
assert isinstance(date1, datetime.datetime)
# The numbers should vary by a very small amount (time it took to execute)
+ diff_python = abs(date2 - date0)
diff = abs(date1 - date2)
- # There should never be a days/seconds difference
+ # There should never be a days difference
assert diff.days == 0
- assert diff.seconds == 0
- # We test that no more than about 0.5 seconds passes here
- # This makes sure that the dates created are very close to the same
- # but if the testing system is incredibly overloaded this should still pass
- assert diff.microseconds < 500000
+ # Since datetime.datetime.today() calls time.time(), and on some platforms
+ # that has 1 second accuracy, we compare this way
+ assert diff.seconds <= diff_python.seconds
def test_chrono_system_clock_roundtrip():
@@ -71,8 +75,36 @@ def test_chrono_system_clock_roundtrip_date():
assert time2.microsecond == 0
-def test_chrono_system_clock_roundtrip_time():
- time1 = datetime.datetime.today().time()
+SKIP_TZ_ENV_ON_WIN = pytest.mark.skipif(
+ "env.WIN", reason="TZ environment variable only supported on POSIX"
+)
+
+
+@pytest.mark.parametrize(
+ "time1",
+ [
+ datetime.datetime.today().time(),
+ datetime.time(0, 0, 0),
+ datetime.time(0, 0, 0, 1),
+ datetime.time(0, 28, 45, 109827),
+ datetime.time(0, 59, 59, 999999),
+ datetime.time(1, 0, 0),
+ datetime.time(5, 59, 59, 0),
+ datetime.time(5, 59, 59, 1),
+ ],
+)
+@pytest.mark.parametrize(
+ "tz",
+ [
+ None,
+ pytest.param("Europe/Brussels", marks=SKIP_TZ_ENV_ON_WIN),
+ pytest.param("Asia/Pyongyang", marks=SKIP_TZ_ENV_ON_WIN),
+ pytest.param("America/New_York", marks=SKIP_TZ_ENV_ON_WIN),
+ ],
+)
+def test_chrono_system_clock_roundtrip_time(time1, tz, monkeypatch):
+ if tz is not None:
+ monkeypatch.setenv("TZ", "/usr/share/zoneinfo/{}".format(tz))
# Roundtrip the time
datetime2 = m.test_chrono2(time1)
@@ -173,4 +205,14 @@ def test_floating_point_duration():
def test_nano_timepoint():
time = datetime.datetime.now()
time1 = m.test_nano_timepoint(time, datetime.timedelta(seconds=60))
- assert(time1 == time + datetime.timedelta(seconds=60))
+ assert time1 == time + datetime.timedelta(seconds=60)
+
+
+def test_chrono_different_resolutions():
+ resolutions = m.different_resolutions()
+ time = datetime.datetime.now()
+ resolutions.timestamp_h = time
+ resolutions.timestamp_m = time
+ resolutions.timestamp_s = time
+ resolutions.timestamp_ms = time
+ resolutions.timestamp_us = time
diff --git a/3rdparty/pybind11/tests/test_class.cpp b/3rdparty/pybind11/tests/test_class.cpp
index 499d0cc5..890fab73 100644
--- a/3rdparty/pybind11/tests/test_class.cpp
+++ b/3rdparty/pybind11/tests/test_class.cpp
@@ -103,7 +103,7 @@ TEST_SUBMODULE(class_, m) {
BaseClass() = default;
BaseClass(const BaseClass &) = default;
BaseClass(BaseClass &&) = default;
- virtual ~BaseClass() {}
+ virtual ~BaseClass() = default;
};
struct DerivedClass1 : BaseClass { };
struct DerivedClass2 : BaseClass { };
@@ -134,6 +134,32 @@ TEST_SUBMODULE(class_, m) {
);
});
+ struct Invalid {};
+
+ // test_type
+ m.def("check_type", [](int category) {
+ // Currently not supported (via a fail at compile time)
+ // See https://github.com/pybind/pybind11/issues/2486
+ // if (category == 2)
+ // return py::type::of<int>();
+ if (category == 1)
+ return py::type::of<DerivedClass1>();
+ else
+ return py::type::of<Invalid>();
+ });
+
+ m.def("get_type_of", [](py::object ob) {
+ return py::type::of(ob);
+ });
+
+ m.def("get_type_classic", [](py::handle h) {
+ return h.get_type();
+ });
+
+ m.def("as_type", [](py::object ob) {
+ return py::type(ob);
+ });
+
// test_mismatched_holder
struct MismatchBase1 { };
struct MismatchDerived1 : MismatchBase1 { };
@@ -142,12 +168,12 @@ TEST_SUBMODULE(class_, m) {
struct MismatchDerived2 : MismatchBase2 { };
m.def("mismatched_holder_1", []() {
- auto mod = py::module::import("__main__");
+ auto mod = py::module_::import("__main__");
py::class_<MismatchBase1, std::shared_ptr<MismatchBase1>>(mod, "MismatchBase1");
py::class_<MismatchDerived1, MismatchBase1>(mod, "MismatchDerived1");
});
m.def("mismatched_holder_2", []() {
- auto mod = py::module::import("__main__");
+ auto mod = py::module_::import("__main__");
py::class_<MismatchBase2>(mod, "MismatchBase2");
py::class_<MismatchDerived2, std::shared_ptr<MismatchDerived2>,
MismatchBase2>(mod, "MismatchDerived2");
@@ -227,6 +253,8 @@ TEST_SUBMODULE(class_, m) {
static void *operator new(size_t s, void *ptr) { py::print("C placement-new", s); return ptr; }
static void operator delete(void *p, size_t s) { py::print("C delete", s); return ::operator delete(p); }
virtual ~AliasedHasOpNewDelSize() = default;
+ AliasedHasOpNewDelSize() = default;
+ AliasedHasOpNewDelSize(const AliasedHasOpNewDelSize&) = delete;
};
struct PyAliasedHasOpNewDelSize : AliasedHasOpNewDelSize {
PyAliasedHasOpNewDelSize() = default;
@@ -277,6 +305,8 @@ TEST_SUBMODULE(class_, m) {
class ProtectedB {
public:
virtual ~ProtectedB() = default;
+ ProtectedB() = default;
+ ProtectedB(const ProtectedB &) = delete;
protected:
virtual int foo() const { return value; }
@@ -287,7 +317,7 @@ TEST_SUBMODULE(class_, m) {
class TrampolineB : public ProtectedB {
public:
- int foo() const override { PYBIND11_OVERLOAD(int, ProtectedB, foo, ); }
+ int foo() const override { PYBIND11_OVERRIDE(int, ProtectedB, foo, ); }
};
class PublicistB : public ProtectedB {
@@ -323,7 +353,7 @@ TEST_SUBMODULE(class_, m) {
// test_reentrant_implicit_conversion_failure
// #1035: issue with runaway reentrant implicit conversion
struct BogusImplicitConversion {
- BogusImplicitConversion(const BogusImplicitConversion &) { }
+ BogusImplicitConversion(const BogusImplicitConversion &) = default;
};
py::class_<BogusImplicitConversion>(m, "BogusImplicitConversion")
@@ -367,19 +397,92 @@ TEST_SUBMODULE(class_, m) {
.def(py::init<>())
.def("ptr", &Aligned::ptr);
#endif
+
+ // test_final
+ struct IsFinal final {};
+ py::class_<IsFinal>(m, "IsFinal", py::is_final());
+
+ // test_non_final_final
+ struct IsNonFinalFinal {};
+ py::class_<IsNonFinalFinal>(m, "IsNonFinalFinal", py::is_final());
+
+ // test_exception_rvalue_abort
+ struct PyPrintDestructor {
+ PyPrintDestructor() = default;
+ ~PyPrintDestructor() {
+ py::print("Print from destructor");
+ }
+ void throw_something() { throw std::runtime_error("error"); }
+ };
+ py::class_<PyPrintDestructor>(m, "PyPrintDestructor")
+ .def(py::init<>())
+ .def("throw_something", &PyPrintDestructor::throw_something);
+
+ // test_multiple_instances_with_same_pointer
+ struct SamePointer {};
+ static SamePointer samePointer;
+ py::class_<SamePointer, std::unique_ptr<SamePointer, py::nodelete>>(m, "SamePointer")
+ .def(py::init([]() { return &samePointer; }))
+ .def("__del__", [](SamePointer&) { py::print("__del__ called"); });
+
+ struct Empty {};
+ py::class_<Empty>(m, "Empty")
+ .def(py::init<>());
+
+ // test_base_and_derived_nested_scope
+ struct BaseWithNested {
+ struct Nested {};
+ };
+
+ struct DerivedWithNested : BaseWithNested {
+ struct Nested {};
+ };
+
+ py::class_<BaseWithNested> baseWithNested_class(m, "BaseWithNested");
+ py::class_<DerivedWithNested, BaseWithNested> derivedWithNested_class(m, "DerivedWithNested");
+ py::class_<BaseWithNested::Nested>(baseWithNested_class, "Nested")
+ .def_static("get_name", []() { return "BaseWithNested::Nested"; });
+ py::class_<DerivedWithNested::Nested>(derivedWithNested_class, "Nested")
+ .def_static("get_name", []() { return "DerivedWithNested::Nested"; });
+
+ // test_register_duplicate_class
+ struct Duplicate {};
+ struct OtherDuplicate {};
+ struct DuplicateNested {};
+ struct OtherDuplicateNested {};
+ m.def("register_duplicate_class_name", [](py::module_ m) {
+ py::class_<Duplicate>(m, "Duplicate");
+ py::class_<OtherDuplicate>(m, "Duplicate");
+ });
+ m.def("register_duplicate_class_type", [](py::module_ m) {
+ py::class_<OtherDuplicate>(m, "OtherDuplicate");
+ py::class_<OtherDuplicate>(m, "YetAnotherDuplicate");
+ });
+ m.def("register_duplicate_nested_class_name", [](py::object gt) {
+ py::class_<DuplicateNested>(gt, "DuplicateNested");
+ py::class_<OtherDuplicateNested>(gt, "DuplicateNested");
+ });
+ m.def("register_duplicate_nested_class_type", [](py::object gt) {
+ py::class_<OtherDuplicateNested>(gt, "OtherDuplicateNested");
+ py::class_<OtherDuplicateNested>(gt, "YetAnotherDuplicateNested");
+ });
}
-template <int N> class BreaksBase { public: virtual ~BreaksBase() = default; };
+template <int N> class BreaksBase { public:
+ virtual ~BreaksBase() = default;
+ BreaksBase() = default;
+ BreaksBase(const BreaksBase&) = delete;
+};
template <int N> class BreaksTramp : public BreaksBase<N> {};
// These should all compile just fine:
-typedef py::class_<BreaksBase<1>, std::unique_ptr<BreaksBase<1>>, BreaksTramp<1>> DoesntBreak1;
-typedef py::class_<BreaksBase<2>, BreaksTramp<2>, std::unique_ptr<BreaksBase<2>>> DoesntBreak2;
-typedef py::class_<BreaksBase<3>, std::unique_ptr<BreaksBase<3>>> DoesntBreak3;
-typedef py::class_<BreaksBase<4>, BreaksTramp<4>> DoesntBreak4;
-typedef py::class_<BreaksBase<5>> DoesntBreak5;
-typedef py::class_<BreaksBase<6>, std::shared_ptr<BreaksBase<6>>, BreaksTramp<6>> DoesntBreak6;
-typedef py::class_<BreaksBase<7>, BreaksTramp<7>, std::shared_ptr<BreaksBase<7>>> DoesntBreak7;
-typedef py::class_<BreaksBase<8>, std::shared_ptr<BreaksBase<8>>> DoesntBreak8;
+using DoesntBreak1 = py::class_<BreaksBase<1>, std::unique_ptr<BreaksBase<1>>, BreaksTramp<1>>;
+using DoesntBreak2 = py::class_<BreaksBase<2>, BreaksTramp<2>, std::unique_ptr<BreaksBase<2>>>;
+using DoesntBreak3 = py::class_<BreaksBase<3>, std::unique_ptr<BreaksBase<3>>>;
+using DoesntBreak4 = py::class_<BreaksBase<4>, BreaksTramp<4>>;
+using DoesntBreak5 = py::class_<BreaksBase<5>>;
+using DoesntBreak6 = py::class_<BreaksBase<6>, std::shared_ptr<BreaksBase<6>>, BreaksTramp<6>>;
+using DoesntBreak7 = py::class_<BreaksBase<7>, BreaksTramp<7>, std::shared_ptr<BreaksBase<7>>>;
+using DoesntBreak8 = py::class_<BreaksBase<8>, std::shared_ptr<BreaksBase<8>>>;
#define CHECK_BASE(N) static_assert(std::is_same<typename DoesntBreak##N::type, BreaksBase<N>>::value, \
"DoesntBreak" #N " has wrong type!")
CHECK_BASE(1); CHECK_BASE(2); CHECK_BASE(3); CHECK_BASE(4); CHECK_BASE(5); CHECK_BASE(6); CHECK_BASE(7); CHECK_BASE(8);
diff --git a/3rdparty/pybind11/tests/test_class.py b/3rdparty/pybind11/tests/test_class.py
index ed63ca85..bdcced96 100644
--- a/3rdparty/pybind11/tests/test_class.py
+++ b/3rdparty/pybind11/tests/test_class.py
@@ -1,5 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
+import env # noqa: F401
+
from pybind11_tests import class_ as m
from pybind11_tests import UserType, ConstructorStats
@@ -23,6 +26,48 @@ def test_instance(msg):
assert cstats.alive() == 0
+def test_type():
+ assert m.check_type(1) == m.DerivedClass1
+ with pytest.raises(RuntimeError) as execinfo:
+ m.check_type(0)
+
+ assert "pybind11::detail::get_type_info: unable to find type info" in str(
+ execinfo.value
+ )
+ assert "Invalid" in str(execinfo.value)
+
+ # Currently not supported
+ # See https://github.com/pybind/pybind11/issues/2486
+ # assert m.check_type(2) == int
+
+
+def test_type_of_py():
+ assert m.get_type_of(1) == int
+ assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
+ assert m.get_type_of(int) == type
+
+
+def test_type_of_classic():
+ assert m.get_type_classic(1) == int
+ assert m.get_type_classic(m.DerivedClass1()) == m.DerivedClass1
+ assert m.get_type_classic(int) == type
+
+
+def test_type_of_py_nodelete():
+ # If the above test deleted the class, this will segfault
+ assert m.get_type_of(m.DerivedClass1()) == m.DerivedClass1
+
+
+def test_as_type_py():
+ assert m.as_type(int) == int
+
+ with pytest.raises(TypeError):
+ assert m.as_type(1) == int
+
+ with pytest.raises(TypeError):
+ assert m.as_type(m.DerivedClass1()) == m.DerivedClass1
+
+
def test_docstrings(doc):
assert doc(UserType) == "A `py::class_` type for testing"
assert UserType.__name__ == "UserType"
@@ -30,18 +75,24 @@ def test_docstrings(doc):
assert UserType.get_value.__name__ == "get_value"
assert UserType.get_value.__module__ == "pybind11_tests"
- assert doc(UserType.get_value) == """
+ assert (
+ doc(UserType.get_value)
+ == """
get_value(self: m.UserType) -> int
Get value using a method
"""
+ )
assert doc(UserType.value) == "Get/set value using a property"
- assert doc(m.NoConstructor.new_instance) == """
+ assert (
+ doc(m.NoConstructor.new_instance)
+ == """
new_instance() -> m.class_.NoConstructor
Return an instance
"""
+ )
def test_qualname(doc):
@@ -50,57 +101,98 @@ def test_qualname(doc):
assert m.NestBase.__qualname__ == "NestBase"
assert m.NestBase.Nested.__qualname__ == "NestBase.Nested"
- assert doc(m.NestBase.__init__) == """
+ assert (
+ doc(m.NestBase.__init__)
+ == """
__init__(self: m.class_.NestBase) -> None
"""
- assert doc(m.NestBase.g) == """
+ )
+ assert (
+ doc(m.NestBase.g)
+ == """
g(self: m.class_.NestBase, arg0: m.class_.NestBase.Nested) -> None
"""
- assert doc(m.NestBase.Nested.__init__) == """
+ )
+ assert (
+ doc(m.NestBase.Nested.__init__)
+ == """
__init__(self: m.class_.NestBase.Nested) -> None
"""
- assert doc(m.NestBase.Nested.fn) == """
+ )
+ assert (
+ doc(m.NestBase.Nested.fn)
+ == """
fn(self: m.class_.NestBase.Nested, arg0: int, arg1: m.class_.NestBase, arg2: m.class_.NestBase.Nested) -> None
""" # noqa: E501 line too long
- assert doc(m.NestBase.Nested.fa) == """
+ )
+ assert (
+ doc(m.NestBase.Nested.fa)
+ == """
fa(self: m.class_.NestBase.Nested, a: int, b: m.class_.NestBase, c: m.class_.NestBase.Nested) -> None
""" # noqa: E501 line too long
+ )
assert m.NestBase.__module__ == "pybind11_tests.class_"
assert m.NestBase.Nested.__module__ == "pybind11_tests.class_"
def test_inheritance(msg):
- roger = m.Rabbit('Rabbit')
+ roger = m.Rabbit("Rabbit")
assert roger.name() + " is a " + roger.species() == "Rabbit is a parrot"
assert m.pet_name_species(roger) == "Rabbit is a parrot"
- polly = m.Pet('Polly', 'parrot')
+ polly = m.Pet("Polly", "parrot")
assert polly.name() + " is a " + polly.species() == "Polly is a parrot"
assert m.pet_name_species(polly) == "Polly is a parrot"
- molly = m.Dog('Molly')
+ molly = m.Dog("Molly")
assert molly.name() + " is a " + molly.species() == "Molly is a dog"
assert m.pet_name_species(molly) == "Molly is a dog"
- fred = m.Hamster('Fred')
+ fred = m.Hamster("Fred")
assert fred.name() + " is a " + fred.species() == "Fred is a rodent"
assert m.dog_bark(molly) == "Woof!"
with pytest.raises(TypeError) as excinfo:
m.dog_bark(polly)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
dog_bark(): incompatible function arguments. The following argument types are supported:
1. (arg0: m.class_.Dog) -> str
Invoked with: <m.class_.Pet object at 0>
"""
+ )
with pytest.raises(TypeError) as excinfo:
m.Chimera("lion", "goat")
assert "No constructor defined!" in str(excinfo.value)
+def test_inheritance_init(msg):
+
+ # Single base
+ class Python(m.Pet):
+ def __init__(self):
+ pass
+
+ with pytest.raises(TypeError) as exc_info:
+ Python()
+ expected = "m.class_.Pet.__init__() must be called when overriding __init__"
+ assert msg(exc_info.value) == expected
+
+ # Multiple bases
+ class RabbitHamster(m.Rabbit, m.Hamster):
+ def __init__(self):
+ m.Rabbit.__init__(self, "RabbitHamster")
+
+ with pytest.raises(TypeError) as exc_info:
+ RabbitHamster()
+ expected = "m.class_.Hamster.__init__() must be called when overriding __init__"
+ assert msg(exc_info.value) == expected
+
+
def test_automatic_upcasting():
assert type(m.return_class_1()).__name__ == "DerivedClass1"
assert type(m.return_class_2()).__name__ == "DerivedClass2"
@@ -126,13 +218,19 @@ def test_mismatched_holder():
with pytest.raises(RuntimeError) as excinfo:
m.mismatched_holder_1()
- assert re.match('generic_type: type ".*MismatchDerived1" does not have a non-default '
- 'holder type while its base ".*MismatchBase1" does', str(excinfo.value))
+ assert re.match(
+ 'generic_type: type ".*MismatchDerived1" does not have a non-default '
+ 'holder type while its base ".*MismatchBase1" does',
+ str(excinfo.value),
+ )
with pytest.raises(RuntimeError) as excinfo:
m.mismatched_holder_2()
- assert re.match('generic_type: type ".*MismatchDerived2" has a non-default holder type '
- 'while its base ".*MismatchBase2" does not', str(excinfo.value))
+ assert re.match(
+ 'generic_type: type ".*MismatchDerived2" has a non-default holder type '
+ 'while its base ".*MismatchBase2" does not',
+ str(excinfo.value),
+ )
def test_override_static():
@@ -164,20 +262,20 @@ def test_operator_new_delete(capture):
a = m.HasOpNewDel()
b = m.HasOpNewDelSize()
d = m.HasOpNewDelBoth()
- assert capture == """
+ assert (
+ capture
+ == """
A new 8
B new 4
D new 32
"""
+ )
sz_alias = str(m.AliasedHasOpNewDelSize.size_alias)
sz_noalias = str(m.AliasedHasOpNewDelSize.size_noalias)
with capture:
c = m.AliasedHasOpNewDelSize()
c2 = SubAliased()
- assert capture == (
- "C new " + sz_noalias + "\n" +
- "C new " + sz_alias + "\n"
- )
+ assert capture == ("C new " + sz_noalias + "\n" + "C new " + sz_alias + "\n")
with capture:
del a
@@ -186,21 +284,21 @@ def test_operator_new_delete(capture):
pytest.gc_collect()
del d
pytest.gc_collect()
- assert capture == """
+ assert (
+ capture
+ == """
A delete
B delete 4
D delete
"""
+ )
with capture:
del c
pytest.gc_collect()
del c2
pytest.gc_collect()
- assert capture == (
- "C delete " + sz_noalias + "\n" +
- "C delete " + sz_alias + "\n"
- )
+ assert capture == ("C delete " + sz_noalias + "\n" + "C delete " + sz_alias + "\n")
def test_bind_protected_functions():
@@ -235,7 +333,7 @@ def test_brace_initialization():
assert b.vec == [123, 456]
-@pytest.unsupported_on_pypy
+@pytest.mark.xfail("env.PYPY")
def test_class_refcount():
"""Instances must correctly increase/decrease the reference count of their types (#1029)"""
from sys import getrefcount
@@ -260,22 +358,109 @@ def test_reentrant_implicit_conversion_failure(msg):
# ensure that there is no runaway reentrant implicit conversion (#1035)
with pytest.raises(TypeError) as excinfo:
m.BogusImplicitConversion(0)
- assert msg(excinfo.value) == '''
+ assert (
+ msg(excinfo.value)
+ == """
__init__(): incompatible constructor arguments. The following argument types are supported:
1. m.class_.BogusImplicitConversion(arg0: m.class_.BogusImplicitConversion)
Invoked with: 0
- '''
+ """
+ )
def test_error_after_conversions():
with pytest.raises(TypeError) as exc_info:
m.test_error_after_conversions("hello")
assert str(exc_info.value).startswith(
- "Unable to convert function return value to a Python type!")
+ "Unable to convert function return value to a Python type!"
+ )
def test_aligned():
if hasattr(m, "Aligned"):
p = m.Aligned().ptr()
assert p % 1024 == 0
+
+
+# https://foss.heptapod.net/pypy/pypy/-/issues/2742
+@pytest.mark.xfail("env.PYPY")
+def test_final():
+ with pytest.raises(TypeError) as exc_info:
+
+ class PyFinalChild(m.IsFinal):
+ pass
+
+ assert str(exc_info.value).endswith("is not an acceptable base type")
+
+
+# https://foss.heptapod.net/pypy/pypy/-/issues/2742
+@pytest.mark.xfail("env.PYPY")
+def test_non_final_final():
+ with pytest.raises(TypeError) as exc_info:
+
+ class PyNonFinalFinalChild(m.IsNonFinalFinal):
+ pass
+
+ assert str(exc_info.value).endswith("is not an acceptable base type")
+
+
+# https://github.com/pybind/pybind11/issues/1878
+def test_exception_rvalue_abort():
+ with pytest.raises(RuntimeError):
+ m.PyPrintDestructor().throw_something()
+
+
+# https://github.com/pybind/pybind11/issues/1568
+def test_multiple_instances_with_same_pointer(capture):
+ n = 100
+ instances = [m.SamePointer() for _ in range(n)]
+ for i in range(n):
+ # We need to reuse the same allocated memory for with a different type,
+ # to ensure the bug in `deregister_instance_impl` is detected. Otherwise
+ # `Py_TYPE(self) == Py_TYPE(it->second)` will still succeed, even though
+ # the `instance` is already deleted.
+ instances[i] = m.Empty()
+ # No assert: if this does not trigger the error
+ # pybind11_fail("pybind11_object_dealloc(): Tried to deallocate unregistered instance!");
+ # and just completes without crashing, we're good.
+
+
+# https://github.com/pybind/pybind11/issues/1624
+def test_base_and_derived_nested_scope():
+ assert issubclass(m.DerivedWithNested, m.BaseWithNested)
+ assert m.BaseWithNested.Nested != m.DerivedWithNested.Nested
+ assert m.BaseWithNested.Nested.get_name() == "BaseWithNested::Nested"
+ assert m.DerivedWithNested.Nested.get_name() == "DerivedWithNested::Nested"
+
+
+def test_register_duplicate_class():
+ import types
+
+ module_scope = types.ModuleType("module_scope")
+ with pytest.raises(RuntimeError) as exc_info:
+ m.register_duplicate_class_name(module_scope)
+ expected = (
+ 'generic_type: cannot initialize type "Duplicate": '
+ "an object with that name is already defined"
+ )
+ assert str(exc_info.value) == expected
+ with pytest.raises(RuntimeError) as exc_info:
+ m.register_duplicate_class_type(module_scope)
+ expected = 'generic_type: type "YetAnotherDuplicate" is already registered!'
+ assert str(exc_info.value) == expected
+
+ class ClassScope:
+ pass
+
+ with pytest.raises(RuntimeError) as exc_info:
+ m.register_duplicate_nested_class_name(ClassScope)
+ expected = (
+ 'generic_type: cannot initialize type "DuplicateNested": '
+ "an object with that name is already defined"
+ )
+ assert str(exc_info.value) == expected
+ with pytest.raises(RuntimeError) as exc_info:
+ m.register_duplicate_nested_class_type(ClassScope)
+ expected = 'generic_type: type "YetAnotherDuplicateNested" is already registered!'
+ assert str(exc_info.value) == expected
diff --git a/3rdparty/pybind11/tests/test_cmake_build/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/CMakeLists.txt
index c9b5fcb2..0c0578ad 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/CMakeLists.txt
@@ -1,56 +1,77 @@
-add_custom_target(test_cmake_build)
+# Built-in in CMake 3.5+
+include(CMakeParseArguments)
-if(CMAKE_VERSION VERSION_LESS 3.1)
- # 3.0 needed for interface library for subdirectory_target/installed_target
- # 3.1 needed for cmake -E env for testing
- return()
-endif()
+add_custom_target(test_cmake_build)
-include(CMakeParseArguments)
function(pybind11_add_build_test name)
cmake_parse_arguments(ARG "INSTALL" "" "" ${ARGN})
- set(build_options "-DCMAKE_PREFIX_PATH=${PROJECT_BINARY_DIR}/mock_install"
- "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
- "-DPYTHON_EXECUTABLE:FILEPATH=${PYTHON_EXECUTABLE}"
- "-DPYBIND11_CPP_STANDARD=${PYBIND11_CPP_STANDARD}")
+ set(build_options "-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}")
+
+ if(PYBIND11_FINDPYTHON)
+ list(APPEND build_options "-DPYBIND11_FINDPYTHON=${PYBIND11_FINDPYTHON}")
+
+ if(DEFINED Python_ROOT_DIR)
+ list(APPEND build_options "-DPython_ROOT_DIR=${Python_ROOT_DIR}")
+ endif()
+
+ list(APPEND build_options "-DPython_EXECUTABLE=${Python_EXECUTABLE}")
+ else()
+ list(APPEND build_options "-DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE}")
+ endif()
+
+ if(DEFINED CMAKE_CXX_STANDARD)
+ list(APPEND build_options "-DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}")
+ endif()
+
if(NOT ARG_INSTALL)
- list(APPEND build_options "-DPYBIND11_PROJECT_DIR=${PROJECT_SOURCE_DIR}")
+ list(APPEND build_options "-DPYBIND11_PROJECT_DIR=${pybind11_SOURCE_DIR}")
+ else()
+ list(APPEND build_options "-DCMAKE_PREFIX_PATH=${pybind11_BINARY_DIR}/mock_install")
endif()
- add_custom_target(test_${name} ${CMAKE_CTEST_COMMAND}
- --quiet --output-log ${name}.log
- --build-and-test "${CMAKE_CURRENT_SOURCE_DIR}/${name}"
- "${CMAKE_CURRENT_BINARY_DIR}/${name}"
- --build-config Release
+ add_custom_target(
+ test_build_${name}
+ ${CMAKE_CTEST_COMMAND}
+ --build-and-test
+ "${CMAKE_CURRENT_SOURCE_DIR}/${name}"
+ "${CMAKE_CURRENT_BINARY_DIR}/${name}"
+ --build-config
+ Release
--build-noclean
- --build-generator ${CMAKE_GENERATOR}
- $<$<BOOL:${CMAKE_GENERATOR_PLATFORM}>:--build-generator-platform> ${CMAKE_GENERATOR_PLATFORM}
- --build-makeprogram ${CMAKE_MAKE_PROGRAM}
- --build-target check
- --build-options ${build_options}
- )
+ --build-generator
+ ${CMAKE_GENERATOR}
+ $<$<BOOL:${CMAKE_GENERATOR_PLATFORM}>:--build-generator-platform>
+ ${CMAKE_GENERATOR_PLATFORM}
+ --build-makeprogram
+ ${CMAKE_MAKE_PROGRAM}
+ --build-target
+ check_${name}
+ --build-options
+ ${build_options})
if(ARG_INSTALL)
- add_dependencies(test_${name} mock_install)
+ add_dependencies(test_build_${name} mock_install)
endif()
- add_dependencies(test_cmake_build test_${name})
+ add_dependencies(test_cmake_build test_build_${name})
endfunction()
pybind11_add_build_test(subdirectory_function)
pybind11_add_build_test(subdirectory_target)
-if(NOT ${PYTHON_MODULE_EXTENSION} MATCHES "pypy")
+if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy")
+ message(STATUS "Skipping embed test on PyPy")
+else()
pybind11_add_build_test(subdirectory_embed)
endif()
if(PYBIND11_INSTALL)
- add_custom_target(mock_install ${CMAKE_COMMAND}
- "-DCMAKE_INSTALL_PREFIX=${PROJECT_BINARY_DIR}/mock_install"
- -P "${PROJECT_BINARY_DIR}/cmake_install.cmake"
- )
+ add_custom_target(
+ mock_install ${CMAKE_COMMAND} "-DCMAKE_INSTALL_PREFIX=${pybind11_BINARY_DIR}/mock_install" -P
+ "${pybind11_BINARY_DIR}/cmake_install.cmake")
pybind11_add_build_test(installed_function INSTALL)
pybind11_add_build_test(installed_target INSTALL)
- if(NOT ${PYTHON_MODULE_EXTENSION} MATCHES "pypy")
+ if(NOT ("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy"
+ ))
pybind11_add_build_test(installed_embed INSTALL)
endif()
endif()
diff --git a/3rdparty/pybind11/tests/test_cmake_build/embed.cpp b/3rdparty/pybind11/tests/test_cmake_build/embed.cpp
index b9581d2f..a3abc8a8 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/embed.cpp
+++ b/3rdparty/pybind11/tests/test_cmake_build/embed.cpp
@@ -12,10 +12,10 @@ int main(int argc, char *argv[]) {
py::scoped_interpreter guard{};
- auto m = py::module::import("test_cmake_build");
+ auto m = py::module_::import("test_cmake_build");
if (m.attr("add")(1, 2).cast<int>() != 3)
throw std::runtime_error("embed.cpp failed");
- py::module::import("sys").attr("argv") = py::make_tuple("test.py", "embed.cpp");
+ py::module_::import("sys").attr("argv") = py::make_tuple("test.py", "embed.cpp");
py::eval_file(test_py_file, py::globals());
}
diff --git a/3rdparty/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt
index f7fc09c2..64ae5c4b 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt
@@ -1,15 +1,26 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.4)
+
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
+
project(test_installed_embed CXX)
-set(CMAKE_MODULE_PATH "")
find_package(pybind11 CONFIG REQUIRED)
message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")
-add_executable(test_cmake_build ../embed.cpp)
-target_link_libraries(test_cmake_build PRIVATE pybind11::embed)
+add_executable(test_installed_embed ../embed.cpp)
+target_link_libraries(test_installed_embed PRIVATE pybind11::embed)
+set_target_properties(test_installed_embed PROPERTIES OUTPUT_NAME test_cmake_build)
# Do not treat includes from IMPORTED target as SYSTEM (Python headers in pybind11::embed).
# This may be needed to resolve header conflicts, e.g. between Python release and debug headers.
-set_target_properties(test_cmake_build PROPERTIES NO_SYSTEM_FROM_IMPORTED ON)
+set_target_properties(test_installed_embed PROPERTIES NO_SYSTEM_FROM_IMPORTED ON)
-add_custom_target(check $<TARGET_FILE:test_cmake_build> ${PROJECT_SOURCE_DIR}/../test.py)
+add_custom_target(check_installed_embed $<TARGET_FILE:test_installed_embed>
+ ${PROJECT_SOURCE_DIR}/../test.py)
diff --git a/3rdparty/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt
index e0c20a8a..1a502863 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt
@@ -1,12 +1,38 @@
-cmake_minimum_required(VERSION 2.8.12)
+cmake_minimum_required(VERSION 3.4)
project(test_installed_module CXX)
-set(CMAKE_MODULE_PATH "")
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
+
+project(test_installed_function CXX)
find_package(pybind11 CONFIG REQUIRED)
-message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")
+message(
+ STATUS "Found pybind11 v${pybind11_VERSION} ${pybind11_VERSION_TYPE}: ${pybind11_INCLUDE_DIRS}")
+
+pybind11_add_module(test_installed_function SHARED NO_EXTRAS ../main.cpp)
+set_target_properties(test_installed_function PROPERTIES OUTPUT_NAME test_cmake_build)
-pybind11_add_module(test_cmake_build SHARED NO_EXTRAS ../main.cpp)
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
-add_custom_target(check ${CMAKE_COMMAND} -E env PYTHONPATH=$<TARGET_FILE_DIR:test_cmake_build>
- ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_NAME})
+add_custom_target(
+ check_installed_function
+ ${CMAKE_COMMAND}
+ -E
+ env
+ PYTHONPATH=$<TARGET_FILE_DIR:test_installed_function>
+ ${_Python_EXECUTABLE}
+ ${PROJECT_SOURCE_DIR}/../test.py
+ ${PROJECT_NAME})
diff --git a/3rdparty/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt
index cd3ae6f7..b38eb774 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt
@@ -1,22 +1,45 @@
-cmake_minimum_required(VERSION 3.0)
-project(test_installed_target CXX)
+cmake_minimum_required(VERSION 3.4)
+
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
-set(CMAKE_MODULE_PATH "")
+project(test_installed_target CXX)
find_package(pybind11 CONFIG REQUIRED)
message(STATUS "Found pybind11 v${pybind11_VERSION}: ${pybind11_INCLUDE_DIRS}")
-add_library(test_cmake_build MODULE ../main.cpp)
+add_library(test_installed_target MODULE ../main.cpp)
-target_link_libraries(test_cmake_build PRIVATE pybind11::module)
+target_link_libraries(test_installed_target PRIVATE pybind11::module)
+set_target_properties(test_installed_target PROPERTIES OUTPUT_NAME test_cmake_build)
-# make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
-set_target_properties(test_cmake_build PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
- SUFFIX "${PYTHON_MODULE_EXTENSION}")
+# Make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
+pybind11_extension(test_installed_target)
# Do not treat includes from IMPORTED target as SYSTEM (Python headers in pybind11::module).
# This may be needed to resolve header conflicts, e.g. between Python release and debug headers.
-set_target_properties(test_cmake_build PROPERTIES NO_SYSTEM_FROM_IMPORTED ON)
+set_target_properties(test_installed_target PROPERTIES NO_SYSTEM_FROM_IMPORTED ON)
+
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
-add_custom_target(check ${CMAKE_COMMAND} -E env PYTHONPATH=$<TARGET_FILE_DIR:test_cmake_build>
- ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_NAME})
+add_custom_target(
+ check_installed_target
+ ${CMAKE_COMMAND}
+ -E
+ env
+ PYTHONPATH=$<TARGET_FILE_DIR:test_installed_target>
+ ${_Python_EXECUTABLE}
+ ${PROJECT_SOURCE_DIR}/../test.py
+ ${PROJECT_NAME})
diff --git a/3rdparty/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt
index 88ba60dd..c7df0cf7 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt
@@ -1,25 +1,39 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.4)
+
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
+
project(test_subdirectory_embed CXX)
-set(PYBIND11_INSTALL ON CACHE BOOL "")
+set(PYBIND11_INSTALL
+ ON
+ CACHE BOOL "")
set(PYBIND11_EXPORT_NAME test_export)
add_subdirectory(${PYBIND11_PROJECT_DIR} pybind11)
# Test basic target functionality
-add_executable(test_cmake_build ../embed.cpp)
-target_link_libraries(test_cmake_build PRIVATE pybind11::embed)
+add_executable(test_subdirectory_embed ../embed.cpp)
+target_link_libraries(test_subdirectory_embed PRIVATE pybind11::embed)
+set_target_properties(test_subdirectory_embed PROPERTIES OUTPUT_NAME test_cmake_build)
-add_custom_target(check $<TARGET_FILE:test_cmake_build> ${PROJECT_SOURCE_DIR}/../test.py)
+add_custom_target(check_subdirectory_embed $<TARGET_FILE:test_subdirectory_embed>
+ ${PROJECT_SOURCE_DIR}/../test.py)
# Test custom export group -- PYBIND11_EXPORT_NAME
add_library(test_embed_lib ../embed.cpp)
target_link_libraries(test_embed_lib PRIVATE pybind11::embed)
-install(TARGETS test_embed_lib
- EXPORT test_export
- ARCHIVE DESTINATION bin
- LIBRARY DESTINATION lib
- RUNTIME DESTINATION lib)
-install(EXPORT test_export
- DESTINATION lib/cmake/test_export/test_export-Targets.cmake)
+install(
+ TARGETS test_embed_lib
+ EXPORT test_export
+ ARCHIVE DESTINATION bin
+ LIBRARY DESTINATION lib
+ RUNTIME DESTINATION lib)
+install(EXPORT test_export DESTINATION lib/cmake/test_export/test_export-Targets.cmake)
diff --git a/3rdparty/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt
index 278007ae..624c600f 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt
@@ -1,8 +1,34 @@
-cmake_minimum_required(VERSION 2.8.12)
-project(test_subdirectory_module CXX)
+cmake_minimum_required(VERSION 3.4)
-add_subdirectory(${PYBIND11_PROJECT_DIR} pybind11)
-pybind11_add_module(test_cmake_build THIN_LTO ../main.cpp)
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
-add_custom_target(check ${CMAKE_COMMAND} -E env PYTHONPATH=$<TARGET_FILE_DIR:test_cmake_build>
- ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_NAME})
+project(test_subdirectory_function CXX)
+
+add_subdirectory("${PYBIND11_PROJECT_DIR}" pybind11)
+pybind11_add_module(test_subdirectory_function ../main.cpp)
+set_target_properties(test_subdirectory_function PROPERTIES OUTPUT_NAME test_cmake_build)
+
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
+
+add_custom_target(
+ check_subdirectory_function
+ ${CMAKE_COMMAND}
+ -E
+ env
+ PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_function>
+ ${_Python_EXECUTABLE}
+ ${PROJECT_SOURCE_DIR}/../test.py
+ ${PROJECT_NAME})
diff --git a/3rdparty/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt b/3rdparty/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
index 6b142d62..2471941f 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt
@@ -1,15 +1,40 @@
-cmake_minimum_required(VERSION 3.0)
+cmake_minimum_required(VERSION 3.4)
+
+# The `cmake_minimum_required(VERSION 3.4...3.18)` syntax does not work with
+# some versions of VS that have a patched CMake 3.11. This forces us to emulate
+# the behavior using the following workaround:
+if(${CMAKE_VERSION} VERSION_LESS 3.18)
+ cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
+else()
+ cmake_policy(VERSION 3.18)
+endif()
+
project(test_subdirectory_target CXX)
add_subdirectory(${PYBIND11_PROJECT_DIR} pybind11)
-add_library(test_cmake_build MODULE ../main.cpp)
+add_library(test_subdirectory_target MODULE ../main.cpp)
+set_target_properties(test_subdirectory_target PROPERTIES OUTPUT_NAME test_cmake_build)
+
+target_link_libraries(test_subdirectory_target PRIVATE pybind11::module)
-target_link_libraries(test_cmake_build PRIVATE pybind11::module)
+# Make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
+pybind11_extension(test_subdirectory_target)
-# make sure result is, for example, test_installed_target.so, not libtest_installed_target.dylib
-set_target_properties(test_cmake_build PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}"
- SUFFIX "${PYTHON_MODULE_EXTENSION}")
+if(DEFINED Python_EXECUTABLE)
+ set(_Python_EXECUTABLE "${Python_EXECUTABLE}")
+elseif(DEFINED PYTHON_EXECUTABLE)
+ set(_Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
+else()
+ message(FATAL_ERROR "No Python executable defined (should not be possible at this stage)")
+endif()
-add_custom_target(check ${CMAKE_COMMAND} -E env PYTHONPATH=$<TARGET_FILE_DIR:test_cmake_build>
- ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/../test.py ${PROJECT_NAME})
+add_custom_target(
+ check_subdirectory_target
+ ${CMAKE_COMMAND}
+ -E
+ env
+ PYTHONPATH=$<TARGET_FILE_DIR:test_subdirectory_target>
+ ${_Python_EXECUTABLE}
+ ${PROJECT_SOURCE_DIR}/../test.py
+ ${PROJECT_NAME})
diff --git a/3rdparty/pybind11/tests/test_cmake_build/test.py b/3rdparty/pybind11/tests/test_cmake_build/test.py
index 1467a61d..87ed5135 100644
--- a/3rdparty/pybind11/tests/test_cmake_build/test.py
+++ b/3rdparty/pybind11/tests/test_cmake_build/test.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import sys
import test_cmake_build
diff --git a/3rdparty/pybind11/tests/test_constants_and_functions.cpp b/3rdparty/pybind11/tests/test_constants_and_functions.cpp
index e8ec74b7..f6077955 100644
--- a/3rdparty/pybind11/tests/test_constants_and_functions.cpp
+++ b/3rdparty/pybind11/tests/test_constants_and_functions.cpp
@@ -74,7 +74,7 @@ struct C {
# pragma GCC diagnostic pop
#endif
};
-}
+} // namespace test_exc_sp
TEST_SUBMODULE(constants_and_functions, m) {
diff --git a/3rdparty/pybind11/tests/test_constants_and_functions.py b/3rdparty/pybind11/tests/test_constants_and_functions.py
index 472682d6..b980ccf1 100644
--- a/3rdparty/pybind11/tests/test_constants_and_functions.py
+++ b/3rdparty/pybind11/tests/test_constants_and_functions.py
@@ -1,4 +1,7 @@
-from pybind11_tests import constants_and_functions as m
+# -*- coding: utf-8 -*-
+import pytest
+
+m = pytest.importorskip("pybind11_tests.constants_and_functions")
def test_constants():
diff --git a/3rdparty/pybind11/tests/test_copy_move.cpp b/3rdparty/pybind11/tests/test_copy_move.cpp
index 98d5e0a0..2704217a 100644
--- a/3rdparty/pybind11/tests/test_copy_move.cpp
+++ b/3rdparty/pybind11/tests/test_copy_move.cpp
@@ -19,14 +19,14 @@ struct empty {
};
struct lacking_copy_ctor : public empty<lacking_copy_ctor> {
- lacking_copy_ctor() {}
+ lacking_copy_ctor() = default;
lacking_copy_ctor(const lacking_copy_ctor& other) = delete;
};
template <> lacking_copy_ctor empty<lacking_copy_ctor>::instance_ = {};
struct lacking_move_ctor : public empty<lacking_move_ctor> {
- lacking_move_ctor() {}
+ lacking_move_ctor() = default;
lacking_move_ctor(const lacking_move_ctor& other) = delete;
lacking_move_ctor(lacking_move_ctor&& other) = delete;
};
@@ -68,8 +68,8 @@ public:
int value;
};
-NAMESPACE_BEGIN(pybind11)
-NAMESPACE_BEGIN(detail)
+PYBIND11_NAMESPACE_BEGIN(pybind11)
+PYBIND11_NAMESPACE_BEGIN(detail)
template <> struct type_caster<MoveOnlyInt> {
PYBIND11_TYPE_CASTER(MoveOnlyInt, _("MoveOnlyInt"));
bool load(handle src, bool) { value = MoveOnlyInt(src.cast<int>()); return true; }
@@ -97,8 +97,8 @@ public:
operator CopyOnlyInt&() { return value; }
template <typename T> using cast_op_type = pybind11::detail::cast_op_type<T>;
};
-NAMESPACE_END(detail)
-NAMESPACE_END(pybind11)
+PYBIND11_NAMESPACE_END(detail)
+PYBIND11_NAMESPACE_END(pybind11)
TEST_SUBMODULE(copy_move_policies, m) {
// test_lacking_copy_ctor
@@ -116,9 +116,9 @@ TEST_SUBMODULE(copy_move_policies, m) {
r += py::cast<MoveOrCopyInt>(o).value; /* moves */
r += py::cast<MoveOnlyInt>(o).value; /* moves */
r += py::cast<CopyOnlyInt>(o).value; /* copies */
- MoveOrCopyInt m1(py::cast<MoveOrCopyInt>(o)); /* moves */
- MoveOnlyInt m2(py::cast<MoveOnlyInt>(o)); /* moves */
- CopyOnlyInt m3(py::cast<CopyOnlyInt>(o)); /* copies */
+ auto m1(py::cast<MoveOrCopyInt>(o)); /* moves */
+ auto m2(py::cast<MoveOnlyInt>(o)); /* moves */
+ auto m3(py::cast<CopyOnlyInt>(o)); /* copies */
r += m1.value + m2.value + m3.value;
return r;
@@ -175,14 +175,20 @@ TEST_SUBMODULE(copy_move_policies, m) {
m.attr("has_optional") = false;
#endif
- // #70 compilation issue if operator new is not public
+ // #70 compilation issue if operator new is not public - simple body added
+ // but not needed on most compilers; MSVC and nvcc don't like a local
+ // struct not having a method defined when declared, since it can not be
+ // added later.
struct PrivateOpNew {
int value = 1;
private:
-#if defined(_MSC_VER)
-# pragma warning(disable: 4822) // warning C4822: local class member function does not have a body
-#endif
- void *operator new(size_t bytes);
+ void *operator new(size_t bytes) {
+ void *ptr = std::malloc(bytes);
+ if (ptr)
+ return ptr;
+ else
+ throw std::bad_alloc{};
+ }
};
py::class_<PrivateOpNew>(m, "PrivateOpNew").def_readonly("value", &PrivateOpNew::value);
m.def("private_op_new_value", []() { return PrivateOpNew(); });
diff --git a/3rdparty/pybind11/tests/test_copy_move.py b/3rdparty/pybind11/tests/test_copy_move.py
index 0e671d96..7e3cc168 100644
--- a/3rdparty/pybind11/tests/test_copy_move.py
+++ b/3rdparty/pybind11/tests/test_copy_move.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import copy_move_policies as m
@@ -18,7 +19,11 @@ def test_move_and_copy_casts():
"""Cast some values in C++ via custom type casters and count the number of moves/copies."""
cstats = m.move_and_copy_cstats()
- c_m, c_mc, c_c = cstats["MoveOnlyInt"], cstats["MoveOrCopyInt"], cstats["CopyOnlyInt"]
+ c_m, c_mc, c_c = (
+ cstats["MoveOnlyInt"],
+ cstats["MoveOrCopyInt"],
+ cstats["CopyOnlyInt"],
+ )
# The type move constructions/assignments below each get incremented: the move assignment comes
# from the type_caster load; the move construction happens when extracting that via a cast or
@@ -42,7 +47,11 @@ def test_move_and_copy_loads():
moves/copies."""
cstats = m.move_and_copy_cstats()
- c_m, c_mc, c_c = cstats["MoveOnlyInt"], cstats["MoveOrCopyInt"], cstats["CopyOnlyInt"]
+ c_m, c_mc, c_c = (
+ cstats["MoveOnlyInt"],
+ cstats["MoveOrCopyInt"],
+ cstats["CopyOnlyInt"],
+ )
assert m.move_only(10) == 10 # 1 move, c_m
assert m.move_or_copy(11) == 11 # 1 move, c_mc
@@ -65,12 +74,16 @@ def test_move_and_copy_loads():
assert c_m.alive() + c_mc.alive() + c_c.alive() == 0
-@pytest.mark.skipif(not m.has_optional, reason='no <optional>')
+@pytest.mark.skipif(not m.has_optional, reason="no <optional>")
def test_move_and_copy_load_optional():
"""Tests move/copy loads of std::optional arguments"""
cstats = m.move_and_copy_cstats()
- c_m, c_mc, c_c = cstats["MoveOnlyInt"], cstats["MoveOrCopyInt"], cstats["CopyOnlyInt"]
+ c_m, c_mc, c_c = (
+ cstats["MoveOnlyInt"],
+ cstats["MoveOrCopyInt"],
+ cstats["CopyOnlyInt"],
+ )
# The extra move/copy constructions below come from the std::optional move (which has to move
# its arguments):
diff --git a/3rdparty/pybind11/tests/test_custom_type_casters.cpp b/3rdparty/pybind11/tests/test_custom_type_casters.cpp
new file mode 100644
index 00000000..d565add2
--- /dev/null
+++ b/3rdparty/pybind11/tests/test_custom_type_casters.cpp
@@ -0,0 +1,127 @@
+/*
+ tests/test_custom_type_casters.cpp -- tests type_caster<T>
+
+ Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
+
+ All rights reserved. Use of this source code is governed by a
+ BSD-style license that can be found in the LICENSE file.
+*/
+
+#include "pybind11_tests.h"
+#include "constructor_stats.h"
+
+
+// py::arg/py::arg_v testing: these arguments just record their argument when invoked
+class ArgInspector1 { public: std::string arg = "(default arg inspector 1)"; };
+class ArgInspector2 { public: std::string arg = "(default arg inspector 2)"; };
+class ArgAlwaysConverts { };
+namespace pybind11 { namespace detail {
+template <> struct type_caster<ArgInspector1> {
+public:
+ PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
+
+ bool load(handle src, bool convert) {
+ value.arg = "loading ArgInspector1 argument " +
+ std::string(convert ? "WITH" : "WITHOUT") + " conversion allowed. "
+ "Argument value = " + (std::string) str(src);
+ return true;
+ }
+
+ static handle cast(const ArgInspector1 &src, return_value_policy, handle) {
+ return str(src.arg).release();
+ }
+};
+template <> struct type_caster<ArgInspector2> {
+public:
+ PYBIND11_TYPE_CASTER(ArgInspector2, _("ArgInspector2"));
+
+ bool load(handle src, bool convert) {
+ value.arg = "loading ArgInspector2 argument " +
+ std::string(convert ? "WITH" : "WITHOUT") + " conversion allowed. "
+ "Argument value = " + (std::string) str(src);
+ return true;
+ }
+
+ static handle cast(const ArgInspector2 &src, return_value_policy, handle) {
+ return str(src.arg).release();
+ }
+};
+template <> struct type_caster<ArgAlwaysConverts> {
+public:
+ PYBIND11_TYPE_CASTER(ArgAlwaysConverts, _("ArgAlwaysConverts"));
+
+ bool load(handle, bool convert) {
+ return convert;
+ }
+
+ static handle cast(const ArgAlwaysConverts &, return_value_policy, handle) {
+ return py::none().release();
+ }
+};
+} // namespace detail
+} // namespace pybind11
+
+// test_custom_caster_destruction
+class DestructionTester {
+public:
+ DestructionTester() { print_default_created(this); }
+ ~DestructionTester() { print_destroyed(this); }
+ DestructionTester(const DestructionTester &) { print_copy_created(this); }
+ DestructionTester(DestructionTester &&) { print_move_created(this); }
+ DestructionTester &operator=(const DestructionTester &) { print_copy_assigned(this); return *this; }
+ DestructionTester &operator=(DestructionTester &&) { print_move_assigned(this); return *this; }
+};
+namespace pybind11 { namespace detail {
+template <> struct type_caster<DestructionTester> {
+ PYBIND11_TYPE_CASTER(DestructionTester, _("DestructionTester"));
+ bool load(handle, bool) { return true; }
+
+ static handle cast(const DestructionTester &, return_value_policy, handle) {
+ return py::bool_(true).release();
+ }
+};
+} // namespace detail
+} // namespace pybind11
+
+TEST_SUBMODULE(custom_type_casters, m) {
+ // test_custom_type_casters
+
+ // test_noconvert_args
+ //
+ // Test converting. The ArgAlwaysConverts is just there to make the first no-conversion pass
+ // fail so that our call always ends up happening via the second dispatch (the one that allows
+ // some conversion).
+ class ArgInspector {
+ public:
+ ArgInspector1 f(ArgInspector1 a, ArgAlwaysConverts) { return a; }
+ std::string g(ArgInspector1 a, const ArgInspector1 &b, int c, ArgInspector2 *d, ArgAlwaysConverts) {
+ return a.arg + "\n" + b.arg + "\n" + std::to_string(c) + "\n" + d->arg;
+ }
+ static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
+ };
+ py::class_<ArgInspector>(m, "ArgInspector")
+ .def(py::init<>())
+ .def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
+ .def("g", &ArgInspector::g, "a"_a.noconvert(), "b"_a, "c"_a.noconvert()=13, "d"_a=ArgInspector2(), py::arg() = ArgAlwaysConverts())
+ .def_static("h", &ArgInspector::h, py::arg().noconvert(), py::arg() = ArgAlwaysConverts())
+ ;
+ m.def("arg_inspect_func", [](ArgInspector2 a, ArgInspector1 b, ArgAlwaysConverts) { return a.arg + "\n" + b.arg; },
+ py::arg().noconvert(false), py::arg_v(nullptr, ArgInspector1()).noconvert(true), py::arg() = ArgAlwaysConverts());
+
+ m.def("floats_preferred", [](double f) { return 0.5 * f; }, py::arg("f"));
+ m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());
+ m.def("ints_preferred", [](int i) { return i / 2; }, py::arg("i"));
+ m.def("ints_only", [](int i) { return i / 2; }, py::arg("i").noconvert());
+
+ // test_custom_caster_destruction
+ // Test that `take_ownership` works on types with a custom type caster when given a pointer
+
+ // default policy: don't take ownership:
+ m.def("custom_caster_no_destroy", []() { static auto *dt = new DestructionTester(); return dt; });
+
+ m.def("custom_caster_destroy", []() { return new DestructionTester(); },
+ py::return_value_policy::take_ownership); // Takes ownership: destroy when finished
+ m.def("custom_caster_destroy_const", []() -> const DestructionTester * { return new DestructionTester(); },
+ py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
+ m.def("destruction_tester_cstats", &ConstructorStats::get<DestructionTester>, py::return_value_policy::reference);
+}
diff --git a/3rdparty/pybind11/tests/test_custom_type_casters.py b/3rdparty/pybind11/tests/test_custom_type_casters.py
new file mode 100644
index 00000000..bb74d54e
--- /dev/null
+++ b/3rdparty/pybind11/tests/test_custom_type_casters.py
@@ -0,0 +1,116 @@
+# -*- coding: utf-8 -*-
+import pytest
+from pybind11_tests import custom_type_casters as m
+
+
+def test_noconvert_args(msg):
+ a = m.ArgInspector()
+ assert (
+ msg(a.f("hi"))
+ == """
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
+ """
+ )
+ assert (
+ msg(a.g("this is a", "this is b"))
+ == """
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
+ 13
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
+ """ # noqa: E501 line too long
+ )
+ assert (
+ msg(a.g("this is a", "this is b", 42))
+ == """
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
+ 42
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
+ """ # noqa: E501 line too long
+ )
+ assert (
+ msg(a.g("this is a", "this is b", 42, "this is d"))
+ == """
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
+ loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
+ 42
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d
+ """
+ )
+ assert (
+ a.h("arg 1")
+ == "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1"
+ )
+ assert (
+ msg(m.arg_inspect_func("A1", "A2"))
+ == """
+ loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
+ loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
+ """
+ )
+
+ assert m.floats_preferred(4) == 2.0
+ assert m.floats_only(4.0) == 2.0
+ with pytest.raises(TypeError) as excinfo:
+ m.floats_only(4)
+ assert (
+ msg(excinfo.value)
+ == """
+ floats_only(): incompatible function arguments. The following argument types are supported:
+ 1. (f: float) -> float
+
+ Invoked with: 4
+ """
+ )
+
+ assert m.ints_preferred(4) == 2
+ assert m.ints_preferred(True) == 0
+ with pytest.raises(TypeError) as excinfo:
+ m.ints_preferred(4.0)
+ assert (
+ msg(excinfo.value)
+ == """
+ ints_preferred(): incompatible function arguments. The following argument types are supported:
+ 1. (i: int) -> int
+
+ Invoked with: 4.0
+ """ # noqa: E501 line too long
+ )
+
+ assert m.ints_only(4) == 2
+ with pytest.raises(TypeError) as excinfo:
+ m.ints_only(4.0)
+ assert (
+ msg(excinfo.value)
+ == """
+ ints_only(): incompatible function arguments. The following argument types are supported:
+ 1. (i: int) -> int
+
+ Invoked with: 4.0
+ """
+ )
+
+
+def test_custom_caster_destruction():
+ """Tests that returning a pointer to a type that gets converted with a custom type caster gets
+ destroyed when the function has py::return_value_policy::take_ownership policy applied."""
+
+ cstats = m.destruction_tester_cstats()
+ # This one *doesn't* have take_ownership: the pointer should be used but not destroyed:
+ z = m.custom_caster_no_destroy()
+ assert cstats.alive() == 1 and cstats.default_constructions == 1
+ assert z
+
+ # take_ownership applied: this constructs a new object, casts it, then destroys it:
+ z = m.custom_caster_destroy()
+ assert z
+ assert cstats.default_constructions == 2
+
+ # Same, but with a const pointer return (which should *not* inhibit destruction):
+ z = m.custom_caster_destroy_const()
+ assert z
+ assert cstats.default_constructions == 3
+
+ # Make sure we still only have the original object (from ..._no_destroy()) alive:
+ assert cstats.alive() == 1
diff --git a/3rdparty/pybind11/tests/test_docstring_options.py b/3rdparty/pybind11/tests/test_docstring_options.py
index 0dbca609..87d80d2d 100644
--- a/3rdparty/pybind11/tests/test_docstring_options.py
+++ b/3rdparty/pybind11/tests/test_docstring_options.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from pybind11_tests import docstring_options as m
@@ -17,10 +18,10 @@ def test_docstring_options():
assert m.test_overloaded3.__doc__ == "Overload docstr"
# options.enable_function_signatures()
- assert m.test_function3.__doc__ .startswith("test_function3(a: int, b: int) -> None")
+ assert m.test_function3.__doc__.startswith("test_function3(a: int, b: int) -> None")
- assert m.test_function4.__doc__ .startswith("test_function4(a: int, b: int) -> None")
- assert m.test_function4.__doc__ .endswith("A custom docstring\n")
+ assert m.test_function4.__doc__.startswith("test_function4(a: int, b: int) -> None")
+ assert m.test_function4.__doc__.endswith("A custom docstring\n")
# options.disable_function_signatures()
# options.disable_user_defined_docstrings()
@@ -30,8 +31,8 @@ def test_docstring_options():
assert m.test_function6.__doc__ == "A custom docstring"
# RAII destructor
- assert m.test_function7.__doc__ .startswith("test_function7(a: int, b: int) -> None")
- assert m.test_function7.__doc__ .endswith("A custom docstring\n")
+ assert m.test_function7.__doc__.startswith("test_function7(a: int, b: int) -> None")
+ assert m.test_function7.__doc__.endswith("A custom docstring\n")
# Suppression of user-defined docstrings for non-function objects
assert not m.DocstringTestFoo.__doc__
diff --git a/3rdparty/pybind11/tests/test_eigen.cpp b/3rdparty/pybind11/tests/test_eigen.cpp
index aba088d7..2cc2243d 100644
--- a/3rdparty/pybind11/tests/test_eigen.cpp
+++ b/3rdparty/pybind11/tests/test_eigen.cpp
@@ -61,8 +61,9 @@ double get_elem(Eigen::Ref<const Eigen::MatrixXd> m) { return m(2, 1); };
// reference is referencing rows/columns correctly).
template <typename MatrixArgType> Eigen::MatrixXd adjust_matrix(MatrixArgType m) {
Eigen::MatrixXd ret(m);
- for (int c = 0; c < m.cols(); c++) for (int r = 0; r < m.rows(); r++)
- ret(r, c) += 10*r + 100*c;
+ for (int c = 0; c < m.cols(); c++)
+ for (int r = 0; r < m.rows(); r++)
+ ret(r, c) += 10*r + 100*c; // NOLINT(clang-analyzer-core.uninitialized.Assign)
return ret;
}
@@ -87,8 +88,6 @@ TEST_SUBMODULE(eigen, m) {
using SparseMatrixR = Eigen::SparseMatrix<float, Eigen::RowMajor>;
using SparseMatrixC = Eigen::SparseMatrix<float>;
- m.attr("have_eigen") = true;
-
// various tests
m.def("double_col", [](const Eigen::VectorXf &x) -> Eigen::VectorXf { return 2.0f * x; });
m.def("double_row", [](const Eigen::RowVectorXf &x) -> Eigen::RowVectorXf { return 2.0f * x; });
@@ -257,7 +256,7 @@ TEST_SUBMODULE(eigen, m) {
m.def("dense_copy_r", [](const DenseMatrixR &m) -> DenseMatrixR { return m; });
m.def("dense_copy_c", [](const DenseMatrixC &m) -> DenseMatrixC { return m; });
// test_sparse, test_sparse_signature
- m.def("sparse_r", [mat]() -> SparseMatrixR { return Eigen::SparseView<Eigen::MatrixXf>(mat); });
+ m.def("sparse_r", [mat]() -> SparseMatrixR { return Eigen::SparseView<Eigen::MatrixXf>(mat); }); //NOLINT(clang-analyzer-core.uninitialized.UndefReturn)
m.def("sparse_c", [mat]() -> SparseMatrixC { return Eigen::SparseView<Eigen::MatrixXf>(mat); });
m.def("sparse_copy_r", [](const SparseMatrixR &m) -> SparseMatrixR { return m; });
m.def("sparse_copy_c", [](const SparseMatrixC &m) -> SparseMatrixC { return m; });
@@ -319,11 +318,11 @@ TEST_SUBMODULE(eigen, m) {
// a new array (np.ones(10)) increases the chances that the temp array will be garbage
// collected and/or that its memory will be overridden with different values.
m.def("get_elem_direct", [](Eigen::Ref<const Eigen::VectorXd> v) {
- py::module::import("numpy").attr("ones")(10);
+ py::module_::import("numpy").attr("ones")(10);
return v(5);
});
m.def("get_elem_indirect", [](std::vector<Eigen::Ref<const Eigen::VectorXd>> v) {
- py::module::import("numpy").attr("ones")(10);
+ py::module_::import("numpy").attr("ones")(10);
return v[0](5);
});
}
diff --git a/3rdparty/pybind11/tests/test_eigen.py b/3rdparty/pybind11/tests/test_eigen.py
index 55d93517..a131dc15 100644
--- a/3rdparty/pybind11/tests/test_eigen.py
+++ b/3rdparty/pybind11/tests/test_eigen.py
@@ -1,17 +1,20 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import ConstructorStats
-pytestmark = pytest.requires_eigen_and_numpy
+np = pytest.importorskip("numpy")
+m = pytest.importorskip("pybind11_tests.eigen")
-with pytest.suppress(ImportError):
- from pybind11_tests import eigen as m
- import numpy as np
- ref = np.array([[ 0., 3, 0, 0, 0, 11],
- [22, 0, 0, 0, 17, 11],
- [ 7, 5, 0, 1, 0, 11],
- [ 0, 0, 0, 0, 0, 11],
- [ 0, 0, 14, 0, 8, 11]])
+ref = np.array(
+ [
+ [0.0, 3, 0, 0, 0, 11],
+ [22, 0, 0, 0, 17, 11],
+ [7, 5, 0, 1, 0, 11],
+ [0, 0, 0, 0, 0, 11],
+ [0, 0, 14, 0, 8, 11],
+ ]
+)
def assert_equal_ref(mat):
@@ -41,28 +44,37 @@ def test_dense():
def test_partially_fixed():
- ref2 = np.array([[0., 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]])
+ ref2 = np.array([[0.0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11], [12, 13, 14, 15]])
np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2), ref2)
np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2), ref2)
np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, 1]), ref2[:, [1]])
np.testing.assert_array_equal(m.partial_copy_four_rm_c(ref2[0, :]), ref2[[0], :])
- np.testing.assert_array_equal(m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)])
np.testing.assert_array_equal(
- m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :])
+ m.partial_copy_four_rm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
+ )
+ np.testing.assert_array_equal(
+ m.partial_copy_four_rm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
+ )
np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2), ref2)
np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2), ref2)
np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, 1]), ref2[:, [1]])
np.testing.assert_array_equal(m.partial_copy_four_cm_c(ref2[0, :]), ref2[[0], :])
- np.testing.assert_array_equal(m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)])
np.testing.assert_array_equal(
- m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :])
+ m.partial_copy_four_cm_r(ref2[:, (0, 2)]), ref2[:, (0, 2)]
+ )
+ np.testing.assert_array_equal(
+ m.partial_copy_four_cm_c(ref2[(3, 1, 2), :]), ref2[(3, 1, 2), :]
+ )
# TypeError should be raise for a shape mismatch
- functions = [m.partial_copy_four_rm_r, m.partial_copy_four_rm_c,
- m.partial_copy_four_cm_r, m.partial_copy_four_cm_c]
- matrix_with_wrong_shape = [[1, 2],
- [3, 4]]
+ functions = [
+ m.partial_copy_four_rm_r,
+ m.partial_copy_four_rm_c,
+ m.partial_copy_four_cm_r,
+ m.partial_copy_four_cm_c,
+ ]
+ matrix_with_wrong_shape = [[1, 2], [3, 4]]
for f in functions:
with pytest.raises(TypeError) as excinfo:
f(matrix_with_wrong_shape)
@@ -70,7 +82,7 @@ def test_partially_fixed():
def test_mutator_descriptors():
- zr = np.arange(30, dtype='float32').reshape(5, 6) # row-major
+ zr = np.arange(30, dtype="float32").reshape(5, 6) # row-major
zc = zr.reshape(6, 5).transpose() # column-major
m.fixed_mutator_r(zr)
@@ -79,16 +91,21 @@ def test_mutator_descriptors():
m.fixed_mutator_a(zc)
with pytest.raises(TypeError) as excinfo:
m.fixed_mutator_r(zc)
- assert ('(arg0: numpy.ndarray[float32[5, 6], flags.writeable, flags.c_contiguous]) -> None'
- in str(excinfo.value))
+ assert (
+ "(arg0: numpy.ndarray[numpy.float32[5, 6],"
+ " flags.writeable, flags.c_contiguous]) -> None" in str(excinfo.value)
+ )
with pytest.raises(TypeError) as excinfo:
m.fixed_mutator_c(zr)
- assert ('(arg0: numpy.ndarray[float32[5, 6], flags.writeable, flags.f_contiguous]) -> None'
- in str(excinfo.value))
+ assert (
+ "(arg0: numpy.ndarray[numpy.float32[5, 6],"
+ " flags.writeable, flags.f_contiguous]) -> None" in str(excinfo.value)
+ )
with pytest.raises(TypeError) as excinfo:
- m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype='float32'))
- assert ('(arg0: numpy.ndarray[float32[5, 6], flags.writeable]) -> None'
- in str(excinfo.value))
+ m.fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype="float32"))
+ assert "(arg0: numpy.ndarray[numpy.float32[5, 6], flags.writeable]) -> None" in str(
+ excinfo.value
+ )
zr.flags.writeable = False
with pytest.raises(TypeError):
m.fixed_mutator_r(zr)
@@ -97,26 +114,26 @@ def test_mutator_descriptors():
def test_cpp_casting():
- assert m.cpp_copy(m.fixed_r()) == 22.
- assert m.cpp_copy(m.fixed_c()) == 22.
- z = np.array([[5., 6], [7, 8]])
- assert m.cpp_copy(z) == 7.
- assert m.cpp_copy(m.get_cm_ref()) == 21.
- assert m.cpp_copy(m.get_rm_ref()) == 21.
- assert m.cpp_ref_c(m.get_cm_ref()) == 21.
- assert m.cpp_ref_r(m.get_rm_ref()) == 21.
+ assert m.cpp_copy(m.fixed_r()) == 22.0
+ assert m.cpp_copy(m.fixed_c()) == 22.0
+ z = np.array([[5.0, 6], [7, 8]])
+ assert m.cpp_copy(z) == 7.0
+ assert m.cpp_copy(m.get_cm_ref()) == 21.0
+ assert m.cpp_copy(m.get_rm_ref()) == 21.0
+ assert m.cpp_ref_c(m.get_cm_ref()) == 21.0
+ assert m.cpp_ref_r(m.get_rm_ref()) == 21.0
with pytest.raises(RuntimeError) as excinfo:
# Can't reference m.fixed_c: it contains floats, m.cpp_ref_any wants doubles
m.cpp_ref_any(m.fixed_c())
- assert 'Unable to cast Python instance' in str(excinfo.value)
+ assert "Unable to cast Python instance" in str(excinfo.value)
with pytest.raises(RuntimeError) as excinfo:
# Can't reference m.fixed_r: it contains floats, m.cpp_ref_any wants doubles
m.cpp_ref_any(m.fixed_r())
- assert 'Unable to cast Python instance' in str(excinfo.value)
- assert m.cpp_ref_any(m.ReturnTester.create()) == 1.
+ assert "Unable to cast Python instance" in str(excinfo.value)
+ assert m.cpp_ref_any(m.ReturnTester.create()) == 1.0
- assert m.cpp_ref_any(m.get_cm_ref()) == 21.
- assert m.cpp_ref_any(m.get_cm_ref()) == 21.
+ assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
+ assert m.cpp_ref_any(m.get_cm_ref()) == 21.0
def test_pass_readonly_array():
@@ -141,14 +158,14 @@ def test_nonunit_stride_from_python():
counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
- for slice_idx, ref_mat in enumerate(slices):
+ for ref_mat in slices:
np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
# Mutator:
m.double_threer(second_row)
m.double_threec(second_col)
- np.testing.assert_array_equal(counting_mat, [[0., 2, 2], [6, 16, 10], [6, 14, 8]])
+ np.testing.assert_array_equal(counting_mat, [[0.0, 2, 2], [6, 16, 10], [6, 14, 8]])
def test_negative_stride_from_python(msg):
@@ -170,33 +187,43 @@ def test_negative_stride_from_python(msg):
counting_3d = np.arange(27.0, dtype=np.float32).reshape((3, 3, 3))
counting_3d = counting_3d[::-1, ::-1, ::-1]
slices = [counting_3d[0, :, :], counting_3d[:, 0, :], counting_3d[:, :, 0]]
- for slice_idx, ref_mat in enumerate(slices):
+ for ref_mat in slices:
np.testing.assert_array_equal(m.double_mat_cm(ref_mat), 2.0 * ref_mat)
np.testing.assert_array_equal(m.double_mat_rm(ref_mat), 2.0 * ref_mat)
# Mutator:
with pytest.raises(TypeError) as excinfo:
m.double_threer(second_row)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
double_threer(): incompatible function arguments. The following argument types are supported:
- 1. (arg0: numpy.ndarray[float32[1, 3], flags.writeable]) -> None
+ 1. (arg0: numpy.ndarray[numpy.float32[1, 3], flags.writeable]) -> None
- Invoked with: """ + repr(np.array([ 5., 4., 3.], dtype='float32')) # noqa: E501 line too long
+ Invoked with: """ # noqa: E501 line too long
+ + repr(np.array([5.0, 4.0, 3.0], dtype="float32"))
+ )
with pytest.raises(TypeError) as excinfo:
m.double_threec(second_col)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
double_threec(): incompatible function arguments. The following argument types are supported:
- 1. (arg0: numpy.ndarray[float32[3, 1], flags.writeable]) -> None
+ 1. (arg0: numpy.ndarray[numpy.float32[3, 1], flags.writeable]) -> None
- Invoked with: """ + repr(np.array([ 7., 4., 1.], dtype='float32')) # noqa: E501 line too long
+ Invoked with: """ # noqa: E501 line too long
+ + repr(np.array([7.0, 4.0, 1.0], dtype="float32"))
+ )
def test_nonunit_stride_to_python():
assert np.all(m.diagonal(ref) == ref.diagonal())
assert np.all(m.diagonal_1(ref) == ref.diagonal(1))
for i in range(-5, 7):
- assert np.all(m.diagonal_n(ref, i) == ref.diagonal(i)), "m.diagonal_n({})".format(i)
+ assert np.all(
+ m.diagonal_n(ref, i) == ref.diagonal(i)
+ ), "m.diagonal_n({})".format(i)
assert np.all(m.block(ref, 2, 1, 3, 3) == ref[2:5, 1:4])
assert np.all(m.block(ref, 1, 4, 4, 2) == ref[1:, 4:])
@@ -206,8 +233,10 @@ def test_nonunit_stride_to_python():
def test_eigen_ref_to_python():
chols = [m.cholesky1, m.cholesky2, m.cholesky3, m.cholesky4]
for i, chol in enumerate(chols, start=1):
- mymat = chol(np.array([[1., 2, 4], [2, 13, 23], [4, 23, 77]]))
- assert np.all(mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])), "cholesky{}".format(i)
+ mymat = chol(np.array([[1.0, 2, 4], [2, 13, 23], [4, 23, 77]]))
+ assert np.all(
+ mymat == np.array([[1, 0, 0], [2, 3, 0], [4, 5, 6]])
+ ), "cholesky{}".format(i)
def assign_both(a1, a2, r, c, v):
@@ -324,8 +353,12 @@ def test_eigen_return_references():
np.testing.assert_array_equal(a_block1, master[3:5, 3:5])
np.testing.assert_array_equal(a_block2, master[2:5, 2:4])
np.testing.assert_array_equal(a_block3, master[6:10, 7:10])
- np.testing.assert_array_equal(a_corn1, master[0::master.shape[0] - 1, 0::master.shape[1] - 1])
- np.testing.assert_array_equal(a_corn2, master[0::master.shape[0] - 1, 0::master.shape[1] - 1])
+ np.testing.assert_array_equal(
+ a_corn1, master[0 :: master.shape[0] - 1, 0 :: master.shape[1] - 1]
+ )
+ np.testing.assert_array_equal(
+ a_corn2, master[0 :: master.shape[0] - 1, 0 :: master.shape[1] - 1]
+ )
np.testing.assert_array_equal(a_copy1, c1want)
np.testing.assert_array_equal(a_copy2, c2want)
@@ -354,16 +387,28 @@ def test_eigen_keepalive():
cstats = ConstructorStats.get(m.ReturnTester)
assert cstats.alive() == 1
unsafe = [a.ref(), a.ref_const(), a.block(1, 2, 3, 4)]
- copies = [a.copy_get(), a.copy_view(), a.copy_ref(), a.copy_ref_const(),
- a.copy_block(4, 3, 2, 1)]
+ copies = [
+ a.copy_get(),
+ a.copy_view(),
+ a.copy_ref(),
+ a.copy_ref_const(),
+ a.copy_block(4, 3, 2, 1),
+ ]
del a
assert cstats.alive() == 0
del unsafe
del copies
- for meth in [m.ReturnTester.get, m.ReturnTester.get_ptr, m.ReturnTester.view,
- m.ReturnTester.view_ptr, m.ReturnTester.ref_safe, m.ReturnTester.ref_const_safe,
- m.ReturnTester.corners, m.ReturnTester.corners_const]:
+ for meth in [
+ m.ReturnTester.get,
+ m.ReturnTester.get_ptr,
+ m.ReturnTester.view,
+ m.ReturnTester.view_ptr,
+ m.ReturnTester.ref_safe,
+ m.ReturnTester.ref_const_safe,
+ m.ReturnTester.corners,
+ m.ReturnTester.corners_const,
+ ]:
assert_keeps_alive(m.ReturnTester, meth)
for meth in [m.ReturnTester.block_safe, m.ReturnTester.block_const]:
@@ -373,18 +418,18 @@ def test_eigen_keepalive():
def test_eigen_ref_mutators():
"""Tests Eigen's ability to mutate numpy values"""
- orig = np.array([[1., 2, 3], [4, 5, 6], [7, 8, 9]])
+ orig = np.array([[1.0, 2, 3], [4, 5, 6], [7, 8, 9]])
zr = np.array(orig)
- zc = np.array(orig, order='F')
+ zc = np.array(orig, order="F")
m.add_rm(zr, 1, 0, 100)
- assert np.all(zr == np.array([[1., 2, 3], [104, 5, 6], [7, 8, 9]]))
+ assert np.all(zr == np.array([[1.0, 2, 3], [104, 5, 6], [7, 8, 9]]))
m.add_cm(zc, 1, 0, 200)
- assert np.all(zc == np.array([[1., 2, 3], [204, 5, 6], [7, 8, 9]]))
+ assert np.all(zc == np.array([[1.0, 2, 3], [204, 5, 6], [7, 8, 9]]))
m.add_any(zr, 1, 0, 20)
- assert np.all(zr == np.array([[1., 2, 3], [124, 5, 6], [7, 8, 9]]))
+ assert np.all(zr == np.array([[1.0, 2, 3], [124, 5, 6], [7, 8, 9]]))
m.add_any(zc, 1, 0, 10)
- assert np.all(zc == np.array([[1., 2, 3], [214, 5, 6], [7, 8, 9]]))
+ assert np.all(zc == np.array([[1.0, 2, 3], [214, 5, 6], [7, 8, 9]]))
# Can't reference a col-major array with a row-major Ref, and vice versa:
with pytest.raises(TypeError):
@@ -405,8 +450,8 @@ def test_eigen_ref_mutators():
cornersr = zr[0::2, 0::2]
cornersc = zc[0::2, 0::2]
- assert np.all(cornersr == np.array([[1., 3], [7, 9]]))
- assert np.all(cornersc == np.array([[1., 3], [7, 9]]))
+ assert np.all(cornersr == np.array([[1.0, 3], [7, 9]]))
+ assert np.all(cornersc == np.array([[1.0, 3], [7, 9]]))
with pytest.raises(TypeError):
m.add_rm(cornersr, 0, 1, 25)
@@ -418,8 +463,8 @@ def test_eigen_ref_mutators():
m.add_cm(cornersc, 0, 1, 25)
m.add_any(cornersr, 0, 1, 25)
m.add_any(cornersc, 0, 1, 44)
- assert np.all(zr == np.array([[1., 2, 28], [4, 5, 6], [7, 8, 9]]))
- assert np.all(zc == np.array([[1., 2, 47], [4, 5, 6], [7, 8, 9]]))
+ assert np.all(zr == np.array([[1.0, 2, 28], [4, 5, 6], [7, 8, 9]]))
+ assert np.all(zc == np.array([[1.0, 2, 47], [4, 5, 6], [7, 8, 9]]))
# You shouldn't be allowed to pass a non-writeable array to a mutating Eigen method:
zro = zr[0:4, 0:4]
@@ -457,7 +502,7 @@ def test_numpy_ref_mutators():
assert not zrro.flags.owndata and not zrro.flags.writeable
zc[1, 2] = 99
- expect = np.array([[11., 12, 13], [21, 22, 99], [31, 32, 33]])
+ expect = np.array([[11.0, 12, 13], [21, 22, 99], [31, 32, 33]])
# We should have just changed zc, of course, but also zcro and the original eigen matrix
assert np.all(zc == expect)
assert np.all(zcro == expect)
@@ -505,18 +550,20 @@ def test_both_ref_mutators():
assert np.all(z == z3)
assert np.all(z == z4)
assert np.all(z == z5)
- expect = np.array([[0., 22, 20], [31, 37, 33], [41, 42, 38]])
+ expect = np.array([[0.0, 22, 20], [31, 37, 33], [41, 42, 38]])
assert np.all(z == expect)
- y = np.array(range(100), dtype='float64').reshape(10, 10)
+ y = np.array(range(100), dtype="float64").reshape(10, 10)
y2 = m.incr_matrix_any(y, 10) # np -> eigen -> np
- y3 = m.incr_matrix_any(y2[0::2, 0::2], -33) # np -> eigen -> np slice -> np -> eigen -> np
+ y3 = m.incr_matrix_any(
+ y2[0::2, 0::2], -33
+ ) # np -> eigen -> np slice -> np -> eigen -> np
y4 = m.even_rows(y3) # numpy -> eigen slice -> (... y3)
y5 = m.even_cols(y4) # numpy -> eigen slice -> (... y4)
y6 = m.incr_matrix_any(y5, 1000) # numpy -> eigen -> (... y5)
# Apply same mutations using just numpy:
- yexpect = np.array(range(100), dtype='float64').reshape(10, 10)
+ yexpect = np.array(range(100), dtype="float64").reshape(10, 10)
yexpect += 10
yexpect[0::2, 0::2] -= 33
yexpect[0::4, 0::4] += 1000
@@ -531,10 +578,14 @@ def test_both_ref_mutators():
def test_nocopy_wrapper():
# get_elem requires a column-contiguous matrix reference, but should be
# callable with other types of matrix (via copying):
- int_matrix_colmajor = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], order='F')
- dbl_matrix_colmajor = np.array(int_matrix_colmajor, dtype='double', order='F', copy=True)
- int_matrix_rowmajor = np.array(int_matrix_colmajor, order='C', copy=True)
- dbl_matrix_rowmajor = np.array(int_matrix_rowmajor, dtype='double', order='C', copy=True)
+ int_matrix_colmajor = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], order="F")
+ dbl_matrix_colmajor = np.array(
+ int_matrix_colmajor, dtype="double", order="F", copy=True
+ )
+ int_matrix_rowmajor = np.array(int_matrix_colmajor, order="C", copy=True)
+ dbl_matrix_rowmajor = np.array(
+ int_matrix_rowmajor, dtype="double", order="C", copy=True
+ )
# All should be callable via get_elem:
assert m.get_elem(int_matrix_colmajor) == 8
@@ -545,32 +596,38 @@ def test_nocopy_wrapper():
# All but the second should fail with m.get_elem_nocopy:
with pytest.raises(TypeError) as excinfo:
m.get_elem_nocopy(int_matrix_colmajor)
- assert ('get_elem_nocopy(): incompatible function arguments.' in str(excinfo.value) and
- ', flags.f_contiguous' in str(excinfo.value))
+ assert "get_elem_nocopy(): incompatible function arguments." in str(
+ excinfo.value
+ ) and ", flags.f_contiguous" in str(excinfo.value)
assert m.get_elem_nocopy(dbl_matrix_colmajor) == 8
with pytest.raises(TypeError) as excinfo:
m.get_elem_nocopy(int_matrix_rowmajor)
- assert ('get_elem_nocopy(): incompatible function arguments.' in str(excinfo.value) and
- ', flags.f_contiguous' in str(excinfo.value))
+ assert "get_elem_nocopy(): incompatible function arguments." in str(
+ excinfo.value
+ ) and ", flags.f_contiguous" in str(excinfo.value)
with pytest.raises(TypeError) as excinfo:
m.get_elem_nocopy(dbl_matrix_rowmajor)
- assert ('get_elem_nocopy(): incompatible function arguments.' in str(excinfo.value) and
- ', flags.f_contiguous' in str(excinfo.value))
+ assert "get_elem_nocopy(): incompatible function arguments." in str(
+ excinfo.value
+ ) and ", flags.f_contiguous" in str(excinfo.value)
# For the row-major test, we take a long matrix in row-major, so only the third is allowed:
with pytest.raises(TypeError) as excinfo:
m.get_elem_rm_nocopy(int_matrix_colmajor)
- assert ('get_elem_rm_nocopy(): incompatible function arguments.' in str(excinfo.value) and
- ', flags.c_contiguous' in str(excinfo.value))
+ assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
+ excinfo.value
+ ) and ", flags.c_contiguous" in str(excinfo.value)
with pytest.raises(TypeError) as excinfo:
m.get_elem_rm_nocopy(dbl_matrix_colmajor)
- assert ('get_elem_rm_nocopy(): incompatible function arguments.' in str(excinfo.value) and
- ', flags.c_contiguous' in str(excinfo.value))
+ assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
+ excinfo.value
+ ) and ", flags.c_contiguous" in str(excinfo.value)
assert m.get_elem_rm_nocopy(int_matrix_rowmajor) == 8
with pytest.raises(TypeError) as excinfo:
m.get_elem_rm_nocopy(dbl_matrix_rowmajor)
- assert ('get_elem_rm_nocopy(): incompatible function arguments.' in str(excinfo.value) and
- ', flags.c_contiguous' in str(excinfo.value))
+ assert "get_elem_rm_nocopy(): incompatible function arguments." in str(
+ excinfo.value
+ ) and ", flags.c_contiguous" in str(excinfo.value)
def test_eigen_ref_life_support():
@@ -588,12 +645,9 @@ def test_eigen_ref_life_support():
def test_special_matrix_objects():
- assert np.all(m.incr_diag(7) == np.diag([1., 2, 3, 4, 5, 6, 7]))
+ assert np.all(m.incr_diag(7) == np.diag([1.0, 2, 3, 4, 5, 6, 7]))
- asymm = np.array([[ 1., 2, 3, 4],
- [ 5, 6, 7, 8],
- [ 9, 10, 11, 12],
- [13, 14, 15, 16]])
+ asymm = np.array([[1.0, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
symm_lower = np.array(asymm)
symm_upper = np.array(asymm)
for i in range(4):
@@ -606,43 +660,55 @@ def test_special_matrix_objects():
def test_dense_signature(doc):
- assert doc(m.double_col) == """
- double_col(arg0: numpy.ndarray[float32[m, 1]]) -> numpy.ndarray[float32[m, 1]]
+ assert (
+ doc(m.double_col)
+ == """
+ double_col(arg0: numpy.ndarray[numpy.float32[m, 1]]) -> numpy.ndarray[numpy.float32[m, 1]]
"""
- assert doc(m.double_row) == """
- double_row(arg0: numpy.ndarray[float32[1, n]]) -> numpy.ndarray[float32[1, n]]
+ )
+ assert (
+ doc(m.double_row)
+ == """
+ double_row(arg0: numpy.ndarray[numpy.float32[1, n]]) -> numpy.ndarray[numpy.float32[1, n]]
"""
- assert doc(m.double_complex) == """
- double_complex(arg0: numpy.ndarray[complex64[m, 1]]) -> numpy.ndarray[complex64[m, 1]]
+ )
+ assert doc(m.double_complex) == (
+ """
+ double_complex(arg0: numpy.ndarray[numpy.complex64[m, 1]])"""
+ """ -> numpy.ndarray[numpy.complex64[m, 1]]
"""
- assert doc(m.double_mat_rm) == """
- double_mat_rm(arg0: numpy.ndarray[float32[m, n]]) -> numpy.ndarray[float32[m, n]]
+ )
+ assert doc(m.double_mat_rm) == (
+ """
+ double_mat_rm(arg0: numpy.ndarray[numpy.float32[m, n]])"""
+ """ -> numpy.ndarray[numpy.float32[m, n]]
"""
+ )
def test_named_arguments():
a = np.array([[1.0, 2], [3, 4], [5, 6]])
b = np.ones((2, 1))
- assert np.all(m.matrix_multiply(a, b) == np.array([[3.], [7], [11]]))
- assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.], [7], [11]]))
- assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.], [7], [11]]))
+ assert np.all(m.matrix_multiply(a, b) == np.array([[3.0], [7], [11]]))
+ assert np.all(m.matrix_multiply(A=a, B=b) == np.array([[3.0], [7], [11]]))
+ assert np.all(m.matrix_multiply(B=b, A=a) == np.array([[3.0], [7], [11]]))
with pytest.raises(ValueError) as excinfo:
m.matrix_multiply(b, a)
- assert str(excinfo.value) == 'Nonconformable matrices!'
+ assert str(excinfo.value) == "Nonconformable matrices!"
with pytest.raises(ValueError) as excinfo:
m.matrix_multiply(A=b, B=a)
- assert str(excinfo.value) == 'Nonconformable matrices!'
+ assert str(excinfo.value) == "Nonconformable matrices!"
with pytest.raises(ValueError) as excinfo:
m.matrix_multiply(B=a, A=b)
- assert str(excinfo.value) == 'Nonconformable matrices!'
+ assert str(excinfo.value) == "Nonconformable matrices!"
-@pytest.requires_eigen_and_scipy
def test_sparse():
+ pytest.importorskip("scipy")
assert_sparse_equal_ref(m.sparse_r())
assert_sparse_equal_ref(m.sparse_c())
assert_sparse_equal_ref(m.sparse_copy_r(m.sparse_r()))
@@ -651,23 +717,33 @@ def test_sparse():
assert_sparse_equal_ref(m.sparse_copy_c(m.sparse_r()))
-@pytest.requires_eigen_and_scipy
def test_sparse_signature(doc):
- assert doc(m.sparse_copy_r) == """
- sparse_copy_r(arg0: scipy.sparse.csr_matrix[float32]) -> scipy.sparse.csr_matrix[float32]
+ pytest.importorskip("scipy")
+ assert (
+ doc(m.sparse_copy_r)
+ == """
+ sparse_copy_r(arg0: scipy.sparse.csr_matrix[numpy.float32]) -> scipy.sparse.csr_matrix[numpy.float32]
""" # noqa: E501 line too long
- assert doc(m.sparse_copy_c) == """
- sparse_copy_c(arg0: scipy.sparse.csc_matrix[float32]) -> scipy.sparse.csc_matrix[float32]
+ )
+ assert (
+ doc(m.sparse_copy_c)
+ == """
+ sparse_copy_c(arg0: scipy.sparse.csc_matrix[numpy.float32]) -> scipy.sparse.csc_matrix[numpy.float32]
""" # noqa: E501 line too long
+ )
def test_issue738():
"""Ignore strides on a length-1 dimension (even if they would be incompatible length > 1)"""
- assert np.all(m.iss738_f1(np.array([[1., 2, 3]])) == np.array([[1., 102, 203]]))
- assert np.all(m.iss738_f1(np.array([[1.], [2], [3]])) == np.array([[1.], [12], [23]]))
-
- assert np.all(m.iss738_f2(np.array([[1., 2, 3]])) == np.array([[1., 102, 203]]))
- assert np.all(m.iss738_f2(np.array([[1.], [2], [3]])) == np.array([[1.], [12], [23]]))
+ assert np.all(m.iss738_f1(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
+ assert np.all(
+ m.iss738_f1(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
+ )
+
+ assert np.all(m.iss738_f2(np.array([[1.0, 2, 3]])) == np.array([[1.0, 102, 203]]))
+ assert np.all(
+ m.iss738_f2(np.array([[1.0], [2], [3]])) == np.array([[1.0], [12], [23]])
+ )
def test_issue1105():
diff --git a/3rdparty/pybind11/tests/test_embed/CMakeLists.txt b/3rdparty/pybind11/tests/test_embed/CMakeLists.txt
index 8b4f1f84..fabcb24e 100644
--- a/3rdparty/pybind11/tests/test_embed/CMakeLists.txt
+++ b/3rdparty/pybind11/tests/test_embed/CMakeLists.txt
@@ -1,41 +1,43 @@
-if(${PYTHON_MODULE_EXTENSION} MATCHES "pypy")
- add_custom_target(cpptest) # Dummy target on PyPy. Embedding is not supported.
+if("${PYTHON_MODULE_EXTENSION}" MATCHES "pypy" OR "${Python_INTERPRETER_ID}" STREQUAL "PyPy")
+ add_custom_target(cpptest) # Dummy target on PyPy. Embedding is not supported.
set(_suppress_unused_variable_warning "${DOWNLOAD_CATCH}")
return()
endif()
-find_package(Catch 1.9.3)
+find_package(Catch 2.13.2)
+
if(CATCH_FOUND)
message(STATUS "Building interpreter tests using Catch v${CATCH_VERSION}")
else()
message(STATUS "Catch not detected. Interpreter tests will be skipped. Install Catch headers"
- " manually or use `cmake -DDOWNLOAD_CATCH=1` to fetch them automatically.")
+ " manually or use `cmake -DDOWNLOAD_CATCH=ON` to fetch them automatically.")
return()
endif()
-add_executable(test_embed
- catch.cpp
- test_interpreter.cpp
-)
-target_include_directories(test_embed PRIVATE ${CATCH_INCLUDE_DIR})
+find_package(Threads REQUIRED)
+
+add_executable(test_embed catch.cpp test_interpreter.cpp)
pybind11_enable_warnings(test_embed)
-if(NOT CMAKE_VERSION VERSION_LESS 3.0)
- target_link_libraries(test_embed PRIVATE pybind11::embed)
-else()
- target_include_directories(test_embed PRIVATE ${PYBIND11_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS})
- target_compile_options(test_embed PRIVATE ${PYBIND11_CPP_STANDARD})
- target_link_libraries(test_embed PRIVATE ${PYTHON_LIBRARIES})
-endif()
+target_link_libraries(test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads)
-find_package(Threads REQUIRED)
-target_link_libraries(test_embed PUBLIC ${CMAKE_THREAD_LIBS_INIT})
+if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
+ file(COPY test_interpreter.py DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
+endif()
-add_custom_target(cpptest COMMAND $<TARGET_FILE:test_embed>
- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+add_custom_target(
+ cpptest
+ COMMAND "$<TARGET_FILE:test_embed>"
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
pybind11_add_module(external_module THIN_LTO external_module.cpp)
-set_target_properties(external_module PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+set_target_properties(external_module PROPERTIES LIBRARY_OUTPUT_DIRECTORY
+ "${CMAKE_CURRENT_BINARY_DIR}")
+foreach(config ${CMAKE_CONFIGURATION_TYPES})
+ string(TOUPPER ${config} config)
+ set_target_properties(external_module PROPERTIES LIBRARY_OUTPUT_DIRECTORY_${config}
+ "${CMAKE_CURRENT_BINARY_DIR}")
+endforeach()
add_dependencies(cpptest external_module)
add_dependencies(check cpptest)
diff --git a/3rdparty/pybind11/tests/test_embed/test_interpreter.cpp b/3rdparty/pybind11/tests/test_embed/test_interpreter.cpp
index 222bd565..944334ce 100644
--- a/3rdparty/pybind11/tests/test_embed/test_interpreter.cpp
+++ b/3rdparty/pybind11/tests/test_embed/test_interpreter.cpp
@@ -30,7 +30,7 @@ private:
class PyWidget final : public Widget {
using Widget::Widget;
- int the_answer() const override { PYBIND11_OVERLOAD_PURE(int, Widget, the_answer); }
+ int the_answer() const override { PYBIND11_OVERRIDE_PURE(int, Widget, the_answer); }
};
PYBIND11_EMBEDDED_MODULE(widget_module, m) {
@@ -51,17 +51,17 @@ PYBIND11_EMBEDDED_MODULE(throw_error_already_set, ) {
}
TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
- auto module = py::module::import("test_interpreter");
- REQUIRE(py::hasattr(module, "DerivedWidget"));
+ auto module_ = py::module_::import("test_interpreter");
+ REQUIRE(py::hasattr(module_, "DerivedWidget"));
- auto locals = py::dict("hello"_a="Hello, World!", "x"_a=5, **module.attr("__dict__"));
+ auto locals = py::dict("hello"_a="Hello, World!", "x"_a=5, **module_.attr("__dict__"));
py::exec(R"(
widget = DerivedWidget("{} - {}".format(hello, x))
message = widget.the_message
)", py::globals(), locals);
REQUIRE(locals["message"].cast<std::string>() == "Hello, World! - 5");
- auto py_widget = module.attr("DerivedWidget")("The question");
+ auto py_widget = module_.attr("DerivedWidget")("The question");
auto message = py_widget.attr("the_message");
REQUIRE(message.cast<std::string>() == "The question");
@@ -70,10 +70,10 @@ TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
}
TEST_CASE("Import error handling") {
- REQUIRE_NOTHROW(py::module::import("widget_module"));
- REQUIRE_THROWS_WITH(py::module::import("throw_exception"),
+ REQUIRE_NOTHROW(py::module_::import("widget_module"));
+ REQUIRE_THROWS_WITH(py::module_::import("throw_exception"),
"ImportError: C++ Error");
- REQUIRE_THROWS_WITH(py::module::import("throw_error_already_set"),
+ REQUIRE_THROWS_WITH(py::module_::import("throw_error_already_set"),
Catch::Contains("ImportError: KeyError"));
}
@@ -107,14 +107,14 @@ bool has_pybind11_internals_static() {
TEST_CASE("Restart the interpreter") {
// Verify pre-restart state.
- REQUIRE(py::module::import("widget_module").attr("add")(1, 2).cast<int>() == 3);
+ REQUIRE(py::module_::import("widget_module").attr("add")(1, 2).cast<int>() == 3);
REQUIRE(has_pybind11_internals_builtin());
REQUIRE(has_pybind11_internals_static());
- REQUIRE(py::module::import("external_module").attr("A")(123).attr("value").cast<int>() == 123);
+ REQUIRE(py::module_::import("external_module").attr("A")(123).attr("value").cast<int>() == 123);
// local and foreign module internals should point to the same internals:
REQUIRE(reinterpret_cast<uintptr_t>(*py::detail::get_internals_pp()) ==
- py::module::import("external_module").attr("internals_at")().cast<uintptr_t>());
+ py::module_::import("external_module").attr("internals_at")().cast<uintptr_t>());
// Restart the interpreter.
py::finalize_interpreter();
@@ -130,14 +130,14 @@ TEST_CASE("Restart the interpreter") {
REQUIRE(has_pybind11_internals_builtin());
REQUIRE(has_pybind11_internals_static());
REQUIRE(reinterpret_cast<uintptr_t>(*py::detail::get_internals_pp()) ==
- py::module::import("external_module").attr("internals_at")().cast<uintptr_t>());
+ py::module_::import("external_module").attr("internals_at")().cast<uintptr_t>());
// Make sure that an interpreter with no get_internals() created until finalize still gets the
// internals destroyed
py::finalize_interpreter();
py::initialize_interpreter();
bool ran = false;
- py::module::import("__main__").attr("internals_destroy_test") =
+ py::module_::import("__main__").attr("internals_destroy_test") =
py::capsule(&ran, [](void *ran) { py::detail::get_internals(); *static_cast<bool *>(ran) = true; });
REQUIRE_FALSE(has_pybind11_internals_builtin());
REQUIRE_FALSE(has_pybind11_internals_static());
@@ -149,20 +149,20 @@ TEST_CASE("Restart the interpreter") {
REQUIRE_FALSE(has_pybind11_internals_static());
// C++ modules can be reloaded.
- auto cpp_module = py::module::import("widget_module");
+ auto cpp_module = py::module_::import("widget_module");
REQUIRE(cpp_module.attr("add")(1, 2).cast<int>() == 3);
// C++ type information is reloaded and can be used in python modules.
- auto py_module = py::module::import("test_interpreter");
+ auto py_module = py::module_::import("test_interpreter");
auto py_widget = py_module.attr("DerivedWidget")("Hello after restart");
REQUIRE(py_widget.attr("the_message").cast<std::string>() == "Hello after restart");
}
TEST_CASE("Subinterpreter") {
// Add tags to the modules in the main interpreter and test the basics.
- py::module::import("__main__").attr("main_tag") = "main interpreter";
+ py::module_::import("__main__").attr("main_tag") = "main interpreter";
{
- auto m = py::module::import("widget_module");
+ auto m = py::module_::import("widget_module");
m.attr("extension_module_tag") = "added to module in main interpreter";
REQUIRE(m.attr("add")(1, 2).cast<int>() == 3);
@@ -181,9 +181,9 @@ TEST_CASE("Subinterpreter") {
REQUIRE(has_pybind11_internals_static());
// Modules tags should be gone.
- REQUIRE_FALSE(py::hasattr(py::module::import("__main__"), "tag"));
+ REQUIRE_FALSE(py::hasattr(py::module_::import("__main__"), "tag"));
{
- auto m = py::module::import("widget_module");
+ auto m = py::module_::import("widget_module");
REQUIRE_FALSE(py::hasattr(m, "extension_module_tag"));
// Function bindings should still work.
@@ -194,8 +194,8 @@ TEST_CASE("Subinterpreter") {
Py_EndInterpreter(sub_tstate);
PyThreadState_Swap(main_tstate);
- REQUIRE(py::hasattr(py::module::import("__main__"), "main_tag"));
- REQUIRE(py::hasattr(py::module::import("widget_module"), "extension_module_tag"));
+ REQUIRE(py::hasattr(py::module_::import("__main__"), "main_tag"));
+ REQUIRE(py::hasattr(py::module_::import("widget_module"), "extension_module_tag"));
}
TEST_CASE("Execution frame") {
@@ -245,7 +245,7 @@ TEST_CASE("Reload module from file") {
// Disable generation of cached bytecode (.pyc files) for this test, otherwise
// Python might pick up an old version from the cache instead of the new versions
// of the .py files generated below
- auto sys = py::module::import("sys");
+ auto sys = py::module_::import("sys");
bool dont_write_bytecode = sys.attr("dont_write_bytecode").cast<bool>();
sys.attr("dont_write_bytecode") = true;
// Reset the value at scope exit
@@ -267,8 +267,8 @@ TEST_CASE("Reload module from file") {
});
// Import the module from file
- auto module = py::module::import(module_name.c_str());
- int result = module.attr("test")().cast<int>();
+ auto module_ = py::module_::import(module_name.c_str());
+ int result = module_.attr("test")().cast<int>();
REQUIRE(result == 1);
// Update the module .py file with a small change
@@ -278,7 +278,7 @@ TEST_CASE("Reload module from file") {
test_module.close();
// Reload the module
- module.reload();
- result = module.attr("test")().cast<int>();
+ module_.reload();
+ result = module_.attr("test")().cast<int>();
REQUIRE(result == 2);
}
diff --git a/3rdparty/pybind11/tests/test_embed/test_interpreter.py b/3rdparty/pybind11/tests/test_embed/test_interpreter.py
index 26a04792..6174ede4 100644
--- a/3rdparty/pybind11/tests/test_embed/test_interpreter.py
+++ b/3rdparty/pybind11/tests/test_embed/test_interpreter.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from widget_module import Widget
diff --git a/3rdparty/pybind11/tests/test_enum.py b/3rdparty/pybind11/tests/test_enum.py
index 7fe9b618..f6b24fc2 100644
--- a/3rdparty/pybind11/tests/test_enum.py
+++ b/3rdparty/pybind11/tests/test_enum.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import enums as m
@@ -6,6 +7,9 @@ def test_unscoped_enum():
assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
assert str(m.EOne) == "UnscopedEnum.EOne"
+ assert repr(m.UnscopedEnum.EOne) == "<UnscopedEnum.EOne: 1>"
+ assert repr(m.UnscopedEnum.ETwo) == "<UnscopedEnum.ETwo: 2>"
+ assert repr(m.EOne) == "<UnscopedEnum.EOne: 1>"
# name property
assert m.UnscopedEnum.EOne.name == "EOne"
@@ -20,18 +24,24 @@ def test_unscoped_enum():
assert m.UnscopedEnum.EOne.name == "EOne"
# __members__ property
- assert m.UnscopedEnum.__members__ == \
- {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree}
+ assert m.UnscopedEnum.__members__ == {
+ "EOne": m.UnscopedEnum.EOne,
+ "ETwo": m.UnscopedEnum.ETwo,
+ "EThree": m.UnscopedEnum.EThree,
+ }
# __members__ readonly
with pytest.raises(AttributeError):
m.UnscopedEnum.__members__ = {}
# __members__ returns a copy
foo = m.UnscopedEnum.__members__
foo["bar"] = "baz"
- assert m.UnscopedEnum.__members__ == \
- {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree}
+ assert m.UnscopedEnum.__members__ == {
+ "EOne": m.UnscopedEnum.EOne,
+ "ETwo": m.UnscopedEnum.ETwo,
+ "EThree": m.UnscopedEnum.EThree,
+ }
- for docstring_line in '''An unscoped enumeration
+ for docstring_line in """An unscoped enumeration
Members:
@@ -39,7 +49,9 @@ Members:
ETwo : Docstring for ETwo
- EThree : Docstring for EThree'''.split('\n'):
+ EThree : Docstring for EThree""".split(
+ "\n"
+ ):
assert docstring_line in m.UnscopedEnum.__doc__
# Unscoped enums will accept ==/!= int comparisons
@@ -49,10 +61,10 @@ Members:
assert y != 3
assert 3 != y
# Compare with None
- assert (y != None) # noqa: E711
+ assert y != None # noqa: E711
assert not (y == None) # noqa: E711
# Compare with an object
- assert (y != object())
+ assert y != object()
assert not (y == object())
# Compare with string
assert y != "2"
@@ -115,10 +127,10 @@ def test_scoped_enum():
assert z != 3
assert 3 != z
# Compare with None
- assert (z != None) # noqa: E711
+ assert z != None # noqa: E711
assert not (z == None) # noqa: E711
# Compare with an object
- assert (z != object())
+ assert z != object()
assert not (z == object())
# Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions)
with pytest.raises(TypeError):
@@ -142,6 +154,8 @@ def test_scoped_enum():
def test_implicit_conversion():
assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
+ assert repr(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "<EMode.EFirstMode: 1>"
+ assert repr(m.ClassWithUnscopedEnum.EFirstMode) == "<EMode.EFirstMode: 1>"
f = m.ClassWithUnscopedEnum.test_function
first = m.ClassWithUnscopedEnum.EFirstMode
@@ -166,7 +180,7 @@ def test_implicit_conversion():
x[f(first)] = 3
x[f(second)] = 4
# Hashing test
- assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}"
+ assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
def test_binary_operators():
@@ -204,3 +218,10 @@ def test_duplicate_enum_name():
with pytest.raises(ValueError) as excinfo:
m.register_bad_enum()
assert str(excinfo.value) == 'SimpleEnum: element "ONE" already exists!'
+
+
+def test_docstring_signatures():
+ for enum_type in [m.ScopedEnum, m.UnscopedEnum]:
+ for attr in enum_type.__dict__.values():
+ # Issue #2623/PR #2637: Add argument names to enum_ methods
+ assert "arg0" not in (attr.__doc__ or "")
diff --git a/3rdparty/pybind11/tests/test_eval.cpp b/3rdparty/pybind11/tests/test_eval.cpp
index e0948219..5416c2ec 100644
--- a/3rdparty/pybind11/tests/test_eval.cpp
+++ b/3rdparty/pybind11/tests/test_eval.cpp
@@ -14,7 +14,7 @@
TEST_SUBMODULE(eval_, m) {
// test_evals
- auto global = py::dict(py::module::import("__main__").attr("__dict__"));
+ auto global = py::dict(py::module_::import("__main__").attr("__dict__"));
m.def("test_eval_statements", [global]() {
auto local = py::dict();
@@ -88,4 +88,12 @@ TEST_SUBMODULE(eval_, m) {
}
return false;
});
+
+ // test_eval_empty_globals
+ m.def("eval_empty_globals", [](py::object global) {
+ if (global.is_none())
+ global = py::dict();
+ auto int_class = py::eval("isinstance(42, int)", global);
+ return global;
+ });
}
diff --git a/3rdparty/pybind11/tests/test_eval.py b/3rdparty/pybind11/tests/test_eval.py
index bda4ef6b..1bb05af0 100644
--- a/3rdparty/pybind11/tests/test_eval.py
+++ b/3rdparty/pybind11/tests/test_eval.py
@@ -1,4 +1,10 @@
+# -*- coding: utf-8 -*-
import os
+
+import pytest
+
+import env # noqa: F401
+
from pybind11_tests import eval_ as m
@@ -10,8 +16,20 @@ def test_evals(capture):
assert m.test_eval()
assert m.test_eval_single_statement()
+ assert m.test_eval_failure()
+
+
+@pytest.mark.xfail("env.PYPY and not env.PY2", raises=RuntimeError)
+def test_eval_file():
filename = os.path.join(os.path.dirname(__file__), "test_eval_call.py")
assert m.test_eval_file(filename)
- assert m.test_eval_failure()
assert m.test_eval_file_failure()
+
+
+def test_eval_empty_globals():
+ assert "__builtins__" in m.eval_empty_globals(None)
+
+ g = {}
+ assert "__builtins__" in m.eval_empty_globals(g)
+ assert "__builtins__" in g
diff --git a/3rdparty/pybind11/tests/test_eval_call.py b/3rdparty/pybind11/tests/test_eval_call.py
index 53c7e721..373b67ba 100644
--- a/3rdparty/pybind11/tests/test_eval_call.py
+++ b/3rdparty/pybind11/tests/test_eval_call.py
@@ -1,4 +1,5 @@
+# -*- coding: utf-8 -*-
# This file is called from 'test_eval.py'
-if 'call_test2' in locals():
+if "call_test2" in locals():
call_test2(y) # noqa: F821 undefined name
diff --git a/3rdparty/pybind11/tests/test_exceptions.cpp b/3rdparty/pybind11/tests/test_exceptions.cpp
index 56cd9bc4..e27c16df 100644
--- a/3rdparty/pybind11/tests/test_exceptions.cpp
+++ b/3rdparty/pybind11/tests/test_exceptions.cpp
@@ -13,7 +13,7 @@
class MyException : public std::exception {
public:
explicit MyException(const char * m) : message{m} {}
- virtual const char * what() const noexcept override {return message.c_str();}
+ const char * what() const noexcept override {return message.c_str();}
private:
std::string message = "";
};
@@ -22,7 +22,7 @@ private:
class MyException2 : public std::exception {
public:
explicit MyException2(const char * m) : message{m} {}
- virtual const char * what() const noexcept override {return message.c_str();}
+ const char * what() const noexcept override {return message.c_str();}
private:
std::string message = "";
};
@@ -32,6 +32,13 @@ class MyException3 {
public:
explicit MyException3(const char * m) : message{m} {}
virtual const char * what() const noexcept {return message.c_str();}
+ // Rule of 5 BEGIN: to preempt compiler warnings.
+ MyException3(const MyException3&) = default;
+ MyException3(MyException3&&) = default;
+ MyException3& operator=(const MyException3&) = default;
+ MyException3& operator=(MyException3&&) = default;
+ virtual ~MyException3() = default;
+ // Rule of 5 END.
private:
std::string message = "";
};
@@ -41,7 +48,7 @@ private:
class MyException4 : public std::exception {
public:
explicit MyException4(const char * m) : message{m} {}
- virtual const char * what() const noexcept override {return message.c_str();}
+ const char * what() const noexcept override {return message.c_str();}
private:
std::string message = "";
};
@@ -65,6 +72,25 @@ struct PythonCallInDestructor {
py::dict d;
};
+
+
+struct PythonAlreadySetInDestructor {
+ PythonAlreadySetInDestructor(const py::str &s) : s(s) {}
+ ~PythonAlreadySetInDestructor() {
+ py::dict foo;
+ try {
+ // Assign to a py::object to force read access of nonexistent dict entry
+ py::object o = foo["bar"];
+ }
+ catch (py::error_already_set& ex) {
+ ex.discard_as_unraisable(s);
+ }
+ }
+
+ py::str s;
+};
+
+
TEST_SUBMODULE(exceptions, m) {
m.def("throw_std_exception", []() {
throw std::runtime_error("This exception was intentionally thrown.");
@@ -144,7 +170,7 @@ TEST_SUBMODULE(exceptions, m) {
m.def("modulenotfound_exception_matches_base", []() {
try {
// On Python >= 3.6, this raises a ModuleNotFoundError, a subclass of ImportError
- py::module::import("nonexistent");
+ py::module_::import("nonexistent");
}
catch (py::error_already_set &ex) {
if (!ex.matches(PyExc_ImportError)) throw;
@@ -183,6 +209,11 @@ TEST_SUBMODULE(exceptions, m) {
return false;
});
+ m.def("python_alreadyset_in_destructor", [](py::str s) {
+ PythonAlreadySetInDestructor alreadyset_in_destructor(s);
+ return true;
+ });
+
// test_nested_throws
m.def("try_catch", [m](py::object exc_type, py::function f, py::args args) {
try { f(*args); }
@@ -194,4 +225,7 @@ TEST_SUBMODULE(exceptions, m) {
}
});
+ // Test repr that cannot be displayed
+ m.def("simple_bool_passthrough", [](bool x) {return x;});
+
}
diff --git a/3rdparty/pybind11/tests/test_exceptions.py b/3rdparty/pybind11/tests/test_exceptions.py
index ac2b3603..95eac709 100644
--- a/3rdparty/pybind11/tests/test_exceptions.py
+++ b/3rdparty/pybind11/tests/test_exceptions.py
@@ -1,3 +1,6 @@
+# -*- coding: utf-8 -*-
+import sys
+
import pytest
from pybind11_tests import exceptions as m
@@ -47,6 +50,33 @@ def test_python_call_in_catch():
assert d["good"] is True
+def test_python_alreadyset_in_destructor(monkeypatch, capsys):
+ hooked = False
+ triggered = [False] # mutable, so Python 2.7 closure can modify it
+
+ if hasattr(sys, "unraisablehook"): # Python 3.8+
+ hooked = True
+ default_hook = sys.unraisablehook
+
+ def hook(unraisable_hook_args):
+ exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
+ if obj == "already_set demo":
+ triggered[0] = True
+ default_hook(unraisable_hook_args)
+ return
+
+ # Use monkeypatch so pytest can apply and remove the patch as appropriate
+ monkeypatch.setattr(sys, "unraisablehook", hook)
+
+ assert m.python_alreadyset_in_destructor("already_set demo") is True
+ if hooked:
+ assert triggered[0] is True
+
+ _, captured_stderr = capsys.readouterr()
+ # Error message is different in Python 2 and 3, check for words that appear in both
+ assert "ignored" in captured_stderr and "already_set demo" in captured_stderr
+
+
def test_exception_matches():
assert m.exception_matches()
assert m.exception_matches_base()
@@ -77,7 +107,9 @@ def test_custom(msg):
# Can we fall-through to the default handler?
with pytest.raises(RuntimeError) as excinfo:
m.throws_logic_error()
- assert msg(excinfo.value) == "this error should fall through to the standard handler"
+ assert (
+ msg(excinfo.value) == "this error should fall through to the standard handler"
+ )
# OverFlow error translation.
with pytest.raises(OverflowError) as excinfo:
@@ -136,7 +168,13 @@ def test_nested_throws(capture):
# C++ -> Python -> C++ -> Python
with capture:
m.try_catch(
- m.MyException5, pycatch, m.MyException, m.try_catch, m.MyException, throw_myex5)
+ m.MyException5,
+ pycatch,
+ m.MyException,
+ m.try_catch,
+ m.MyException,
+ throw_myex5,
+ )
assert str(capture).startswith("MyException5: nested error 5")
# C++ -> Python -> C++
@@ -148,3 +186,13 @@ def test_nested_throws(capture):
with pytest.raises(m.MyException5) as excinfo:
m.try_catch(m.MyException, pycatch, m.MyException, m.throws5)
assert str(excinfo.value) == "this is a helper-defined translated exception"
+
+
+# This can often happen if you wrap a pybind11 class in a Python wrapper
+def test_invalid_repr():
+ class MyRepr(object):
+ def __repr__(self):
+ raise AttributeError("Example error")
+
+ with pytest.raises(TypeError):
+ m.simple_bool_passthrough(MyRepr())
diff --git a/3rdparty/pybind11/tests/test_factory_constructors.cpp b/3rdparty/pybind11/tests/test_factory_constructors.cpp
index 5cfbfdc3..f42d1f29 100644
--- a/3rdparty/pybind11/tests/test_factory_constructors.cpp
+++ b/3rdparty/pybind11/tests/test_factory_constructors.cpp
@@ -11,6 +11,7 @@
#include "pybind11_tests.h"
#include "constructor_stats.h"
#include <cmath>
+#include <new>
// Classes for testing python construction via C++ factory function:
// Not publicly constructible, copyable, or movable:
@@ -57,13 +58,13 @@ class TestFactory4 : public TestFactory3 {
public:
TestFactory4() : TestFactory3() { print_default_created(this); }
TestFactory4(int v) : TestFactory3(v) { print_created(this, v); }
- virtual ~TestFactory4() { print_destroyed(this); }
+ ~TestFactory4() override { print_destroyed(this); }
};
// Another class for an invalid downcast test
class TestFactory5 : public TestFactory3 {
public:
TestFactory5(int i) : TestFactory3(i) { print_created(this, i); }
- virtual ~TestFactory5() { print_destroyed(this); }
+ ~TestFactory5() override { print_destroyed(this); }
};
class TestFactory6 {
@@ -87,8 +88,8 @@ public:
PyTF6(PyTF6 &&f) : TestFactory6(std::move(f)) { print_move_created(this); }
PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); }
- virtual ~PyTF6() { print_destroyed(this); }
- int get() override { PYBIND11_OVERLOAD(int, TestFactory6, get, /*no args*/); }
+ ~PyTF6() override { print_destroyed(this); }
+ int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); }
};
class TestFactory7 {
@@ -108,8 +109,8 @@ public:
PyTF7(int i) : TestFactory7(i) { alias = true; print_created(this, i); }
PyTF7(PyTF7 &&f) : TestFactory7(std::move(f)) { print_move_created(this); }
PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); }
- virtual ~PyTF7() { print_destroyed(this); }
- int get() override { PYBIND11_OVERLOAD(int, TestFactory7, get, /*no args*/); }
+ ~PyTF7() override { print_destroyed(this); }
+ int get() override { PYBIND11_OVERRIDE(int, TestFactory7, get, /*no args*/); }
};
@@ -141,7 +142,7 @@ public:
TEST_SUBMODULE(factory_constructors, m) {
// Define various trivial types to allow simpler overload resolution:
- py::module m_tag = m.def_submodule("tag");
+ py::module_ m_tag = m.def_submodule("tag");
#define MAKE_TAG_TYPE(Name) \
struct Name##_tag {}; \
py::class_<Name##_tag>(m_tag, #Name "_tag").def(py::init<>()); \
@@ -154,6 +155,8 @@ TEST_SUBMODULE(factory_constructors, m) {
MAKE_TAG_TYPE(TF4);
MAKE_TAG_TYPE(TF5);
MAKE_TAG_TYPE(null_ptr);
+ MAKE_TAG_TYPE(null_unique_ptr);
+ MAKE_TAG_TYPE(null_shared_ptr);
MAKE_TAG_TYPE(base);
MAKE_TAG_TYPE(invalid_base);
MAKE_TAG_TYPE(alias);
@@ -194,6 +197,8 @@ TEST_SUBMODULE(factory_constructors, m) {
// Returns nullptr:
.def(py::init([](null_ptr_tag) { return (TestFactory3 *) nullptr; }))
+ .def(py::init([](null_unique_ptr_tag) { return std::unique_ptr<TestFactory3>(); }))
+ .def(py::init([](null_shared_ptr_tag) { return std::shared_ptr<TestFactory3>(); }))
.def_readwrite("value", &TestFactory3::value)
;
diff --git a/3rdparty/pybind11/tests/test_factory_constructors.py b/3rdparty/pybind11/tests/test_factory_constructors.py
index 78a3910a..ffcce6fd 100644
--- a/3rdparty/pybind11/tests/test_factory_constructors.py
+++ b/3rdparty/pybind11/tests/test_factory_constructors.py
@@ -1,6 +1,9 @@
+# -*- coding: utf-8 -*-
import pytest
import re
+import env # noqa: F401
+
from pybind11_tests import factory_constructors as m
from pybind11_tests.factory_constructors import tag
from pybind11_tests import ConstructorStats
@@ -9,7 +12,10 @@ from pybind11_tests import ConstructorStats
def test_init_factory_basic():
"""Tests py::init_factory() wrapper around various ways of returning the object"""
- cstats = [ConstructorStats.get(c) for c in [m.TestFactory1, m.TestFactory2, m.TestFactory3]]
+ cstats = [
+ ConstructorStats.get(c)
+ for c in [m.TestFactory1, m.TestFactory2, m.TestFactory3]
+ ]
cstats[0].alive() # force gc
n_inst = ConstructorStats.detail_reg_inst()
@@ -38,9 +44,12 @@ def test_init_factory_basic():
z3 = m.TestFactory3("bye")
assert z3.value == "bye"
- with pytest.raises(TypeError) as excinfo:
- m.TestFactory3(tag.null_ptr)
- assert str(excinfo.value) == "pybind11::init(): factory function returned nullptr"
+ for null_ptr_kind in [tag.null_ptr, tag.null_unique_ptr, tag.null_shared_ptr]:
+ with pytest.raises(TypeError) as excinfo:
+ m.TestFactory3(null_ptr_kind)
+ assert (
+ str(excinfo.value) == "pybind11::init(): factory function returned nullptr"
+ )
assert [i.alive() for i in cstats] == [3, 3, 3]
assert ConstructorStats.detail_reg_inst() == n_inst + 9
@@ -55,7 +64,7 @@ def test_init_factory_basic():
assert [i.values() for i in cstats] == [
["3", "hi!"],
["7", "hi again"],
- ["42", "bye"]
+ ["42", "bye"],
]
assert [i.default_constructions for i in cstats] == [1, 1, 1]
@@ -63,7 +72,9 @@ def test_init_factory_basic():
def test_init_factory_signature(msg):
with pytest.raises(TypeError) as excinfo:
m.TestFactory1("invalid", "constructor", "arguments")
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
__init__(): incompatible constructor arguments. The following argument types are supported:
1. m.factory_constructors.TestFactory1(arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int)
2. m.factory_constructors.TestFactory1(arg0: str)
@@ -72,8 +83,11 @@ def test_init_factory_signature(msg):
Invoked with: 'invalid', 'constructor', 'arguments'
""" # noqa: E501 line too long
+ )
- assert msg(m.TestFactory1.__init__.__doc__) == """
+ assert (
+ msg(m.TestFactory1.__init__.__doc__)
+ == """
__init__(*args, **kwargs)
Overloaded function.
@@ -85,12 +99,16 @@ def test_init_factory_signature(msg):
4. __init__(self: m.factory_constructors.TestFactory1, arg0: handle, arg1: int, arg2: handle) -> None
""" # noqa: E501 line too long
+ )
def test_init_factory_casting():
"""Tests py::init_factory() wrapper with various upcasting and downcasting returns"""
- cstats = [ConstructorStats.get(c) for c in [m.TestFactory3, m.TestFactory4, m.TestFactory5]]
+ cstats = [
+ ConstructorStats.get(c)
+ for c in [m.TestFactory3, m.TestFactory4, m.TestFactory5]
+ ]
cstats[0].alive() # force gc
n_inst = ConstructorStats.detail_reg_inst()
@@ -128,7 +146,7 @@ def test_init_factory_casting():
assert [i.values() for i in cstats] == [
["4", "5", "6", "7", "8"],
["4", "5", "8"],
- ["6", "7"]
+ ["6", "7"],
]
@@ -198,7 +216,7 @@ def test_init_factory_alias():
assert [i.values() for i in cstats] == [
["1", "8", "3", "4", "5", "6", "123", "10", "47"],
- ["hi there", "3", "4", "6", "move", "123", "why hello!", "move", "47"]
+ ["hi there", "3", "4", "6", "move", "123", "why hello!", "move", "47"],
]
@@ -262,9 +280,11 @@ def test_init_factory_dual():
assert not g1.has_alias()
with pytest.raises(TypeError) as excinfo:
PythFactory7(tag.shared_ptr, tag.invalid_base, 14)
- assert (str(excinfo.value) ==
- "pybind11::init(): construction failed: returned holder-wrapped instance is not an "
- "alias instance")
+ assert (
+ str(excinfo.value)
+ == "pybind11::init(): construction failed: returned holder-wrapped instance is not an "
+ "alias instance"
+ )
assert [i.alive() for i in cstats] == [13, 7]
assert ConstructorStats.detail_reg_inst() == n_inst + 13
@@ -278,7 +298,7 @@ def test_init_factory_dual():
assert [i.values() for i in cstats] == [
["1", "2", "3", "4", "5", "6", "7", "8", "9", "100", "11", "12", "13", "14"],
- ["2", "4", "6", "8", "9", "100", "12"]
+ ["2", "4", "6", "8", "9", "100", "12"],
]
@@ -288,7 +308,7 @@ def test_no_placement_new(capture):
with capture:
a = m.NoPlacementNew(123)
- found = re.search(r'^operator new called, returning (\d+)\n$', str(capture))
+ found = re.search(r"^operator new called, returning (\d+)\n$", str(capture))
assert found
assert a.i == 123
with capture:
@@ -299,7 +319,7 @@ def test_no_placement_new(capture):
with capture:
b = m.NoPlacementNew()
- found = re.search(r'^operator new called, returning (\d+)\n$', str(capture))
+ found = re.search(r"^operator new called, returning (\d+)\n$", str(capture))
assert found
assert b.i == 100
with capture:
@@ -327,19 +347,21 @@ def create_and_destroy(*args):
def strip_comments(s):
- return re.sub(r'\s+#.*', '', s)
+ return re.sub(r"\s+#.*", "", s)
-def test_reallocations(capture, msg):
+def test_reallocation_a(capture, msg):
"""When the constructor is overloaded, previous overloads can require a preallocated value.
This test makes sure that such preallocated values only happen when they might be necessary,
- and that they are deallocated properly"""
+ and that they are deallocated properly."""
pytest.gc_collect()
with capture:
create_and_destroy(1)
- assert msg(capture) == """
+ assert (
+ msg(capture)
+ == """
noisy new
noisy placement new
NoisyAlloc(int 1)
@@ -347,9 +369,14 @@ def test_reallocations(capture, msg):
~NoisyAlloc()
noisy delete
"""
+ )
+
+
+def test_reallocation_b(capture, msg):
with capture:
create_and_destroy(1.5)
- assert msg(capture) == strip_comments("""
+ assert msg(capture) == strip_comments(
+ """
noisy new # allocation required to attempt first overload
noisy delete # have to dealloc before considering factory init overload
noisy new # pointer factory calling "new", part 1: allocation
@@ -357,43 +384,59 @@ def test_reallocations(capture, msg):
---
~NoisyAlloc() # Destructor
noisy delete # operator delete
- """)
+ """
+ )
+
+def test_reallocation_c(capture, msg):
with capture:
create_and_destroy(2, 3)
- assert msg(capture) == strip_comments("""
+ assert msg(capture) == strip_comments(
+ """
noisy new # pointer factory calling "new", allocation
NoisyAlloc(int 2) # constructor
---
~NoisyAlloc() # Destructor
noisy delete # operator delete
- """)
+ """
+ )
+
+def test_reallocation_d(capture, msg):
with capture:
create_and_destroy(2.5, 3)
- assert msg(capture) == strip_comments("""
+ assert msg(capture) == strip_comments(
+ """
NoisyAlloc(double 2.5) # construction (local func variable: operator_new not called)
noisy new # return-by-value "new" part 1: allocation
~NoisyAlloc() # moved-away local func variable destruction
---
~NoisyAlloc() # Destructor
noisy delete # operator delete
- """)
+ """
+ )
+
+def test_reallocation_e(capture, msg):
with capture:
create_and_destroy(3.5, 4.5)
- assert msg(capture) == strip_comments("""
+ assert msg(capture) == strip_comments(
+ """
noisy new # preallocation needed before invoking placement-new overload
noisy placement new # Placement new
NoisyAlloc(double 3.5) # construction
---
~NoisyAlloc() # Destructor
noisy delete # operator delete
- """)
+ """
+ )
+
+def test_reallocation_f(capture, msg):
with capture:
create_and_destroy(4, 0.5)
- assert msg(capture) == strip_comments("""
+ assert msg(capture) == strip_comments(
+ """
noisy new # preallocation needed before invoking placement-new overload
noisy delete # deallocation of preallocated storage
noisy new # Factory pointer allocation
@@ -401,11 +444,15 @@ def test_reallocations(capture, msg):
---
~NoisyAlloc() # Destructor
noisy delete # operator delete
- """)
+ """
+ )
+
+def test_reallocation_g(capture, msg):
with capture:
create_and_destroy(5, "hi")
- assert msg(capture) == strip_comments("""
+ assert msg(capture) == strip_comments(
+ """
noisy new # preallocation needed before invoking first placement new
noisy delete # delete before considering new-style constructor
noisy new # preallocation for second placement new
@@ -414,13 +461,15 @@ def test_reallocations(capture, msg):
---
~NoisyAlloc() # Destructor
noisy delete # operator delete
- """)
+ """
+ )
-@pytest.unsupported_on_py2
+@pytest.mark.skipif("env.PY2")
def test_invalid_self():
"""Tests invocation of the pybind-registered base class with an invalid `self` argument. You
can only actually do this on Python 3: Python 2 raises an exception itself if you try."""
+
class NotPybindDerived(object):
pass
@@ -444,16 +493,26 @@ def test_invalid_self():
a = m.TestFactory2(tag.pointer, 1)
m.TestFactory6.__init__(a, tag.alias, 1)
elif bad == 3:
- m.TestFactory6.__init__(NotPybindDerived.__new__(NotPybindDerived), tag.base, 1)
+ m.TestFactory6.__init__(
+ NotPybindDerived.__new__(NotPybindDerived), tag.base, 1
+ )
elif bad == 4:
- m.TestFactory6.__init__(NotPybindDerived.__new__(NotPybindDerived), tag.alias, 1)
+ m.TestFactory6.__init__(
+ NotPybindDerived.__new__(NotPybindDerived), tag.alias, 1
+ )
for arg in (1, 2):
with pytest.raises(TypeError) as excinfo:
BrokenTF1(arg)
- assert str(excinfo.value) == "__init__(self, ...) called with invalid `self` argument"
+ assert (
+ str(excinfo.value)
+ == "__init__(self, ...) called with invalid `self` argument"
+ )
for arg in (1, 2, 3, 4):
with pytest.raises(TypeError) as excinfo:
BrokenTF6(arg)
- assert str(excinfo.value) == "__init__(self, ...) called with invalid `self` argument"
+ assert (
+ str(excinfo.value)
+ == "__init__(self, ...) called with invalid `self` argument"
+ )
diff --git a/3rdparty/pybind11/tests/test_gil_scoped.cpp b/3rdparty/pybind11/tests/test_gil_scoped.cpp
index 76c17fdc..b6a45a5f 100644
--- a/3rdparty/pybind11/tests/test_gil_scoped.cpp
+++ b/3rdparty/pybind11/tests/test_gil_scoped.cpp
@@ -13,17 +13,19 @@
class VirtClass {
public:
- virtual ~VirtClass() {}
+ virtual ~VirtClass() = default;
+ VirtClass() = default;
+ VirtClass(const VirtClass&) = delete;
virtual void virtual_func() {}
virtual void pure_virtual_func() = 0;
};
class PyVirtClass : public VirtClass {
void virtual_func() override {
- PYBIND11_OVERLOAD(void, VirtClass, virtual_func,);
+ PYBIND11_OVERRIDE(void, VirtClass, virtual_func,);
}
void pure_virtual_func() override {
- PYBIND11_OVERLOAD_PURE(void, VirtClass, pure_virtual_func,);
+ PYBIND11_OVERRIDE_PURE(void, VirtClass, pure_virtual_func,);
}
};
@@ -43,7 +45,7 @@ TEST_SUBMODULE(gil_scoped, m) {
[](VirtClass &virt) { virt.pure_virtual_func(); });
m.def("test_cross_module_gil",
[]() {
- auto cm = py::module::import("cross_module_gil_utils");
+ auto cm = py::module_::import("cross_module_gil_utils");
auto gil_acquire = reinterpret_cast<void (*)()>(
PyLong_AsVoidPtr(cm.attr("gil_acquire_funcaddr").ptr()));
py::gil_scoped_release gil_release;
diff --git a/3rdparty/pybind11/tests/test_gil_scoped.py b/3rdparty/pybind11/tests/test_gil_scoped.py
index 1548337c..0a1d6274 100644
--- a/3rdparty/pybind11/tests/test_gil_scoped.py
+++ b/3rdparty/pybind11/tests/test_gil_scoped.py
@@ -1,5 +1,7 @@
+# -*- coding: utf-8 -*-
import multiprocessing
import threading
+
from pybind11_tests import gil_scoped as m
@@ -19,6 +21,7 @@ def _run_in_process(target, *args, **kwargs):
def _python_to_cpp_to_python():
"""Calls different C++ functions that come back to Python."""
+
class ExtendedVirtClass(m.VirtClass):
def virtual_func(self):
pass
@@ -48,6 +51,7 @@ def _python_to_cpp_to_python_from_threads(num_threads, parallel=False):
thread.join()
+# TODO: FIXME, sometimes returns -11 (segfault) instead of 0 on macOS Python 3.9
def test_python_to_cpp_to_python_from_thread():
"""Makes sure there is no GIL deadlock when running in a thread.
@@ -56,6 +60,7 @@ def test_python_to_cpp_to_python_from_thread():
assert _run_in_process(_python_to_cpp_to_python_from_threads, 1) == 0
+# TODO: FIXME on macOS Python 3.9
def test_python_to_cpp_to_python_from_thread_multiple_parallel():
"""Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
@@ -64,14 +69,18 @@ def test_python_to_cpp_to_python_from_thread_multiple_parallel():
assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=True) == 0
+# TODO: FIXME on macOS Python 3.9
def test_python_to_cpp_to_python_from_thread_multiple_sequential():
"""Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
It runs in a separate process to be able to stop and assert if it deadlocks.
"""
- assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0
+ assert (
+ _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0
+ )
+# TODO: FIXME on macOS Python 3.9
def test_python_to_cpp_to_python_from_process():
"""Makes sure there is no GIL deadlock when using processes.
diff --git a/3rdparty/pybind11/tests/test_iostream.cpp b/3rdparty/pybind11/tests/test_iostream.cpp
index e67f88af..e9161505 100644
--- a/3rdparty/pybind11/tests/test_iostream.cpp
+++ b/3rdparty/pybind11/tests/test_iostream.cpp
@@ -37,7 +37,7 @@ TEST_SUBMODULE(iostream, m) {
});
m.def("captured_output", [](std::string msg) {
- py::scoped_ostream_redirect redir(std::cout, py::module::import("sys").attr("stdout"));
+ py::scoped_ostream_redirect redir(std::cout, py::module_::import("sys").attr("stdout"));
std::cout << msg << std::flush;
});
@@ -46,7 +46,7 @@ TEST_SUBMODULE(iostream, m) {
py::arg("msg"), py::arg("flush")=true);
m.def("captured_err", [](std::string msg) {
- py::scoped_ostream_redirect redir(std::cerr, py::module::import("sys").attr("stderr"));
+ py::scoped_ostream_redirect redir(std::cerr, py::module_::import("sys").attr("stderr"));
std::cerr << msg << std::flush;
});
@@ -65,8 +65,8 @@ TEST_SUBMODULE(iostream, m) {
});
m.def("captured_dual", [](std::string msg, std::string emsg) {
- py::scoped_ostream_redirect redirout(std::cout, py::module::import("sys").attr("stdout"));
- py::scoped_ostream_redirect redirerr(std::cerr, py::module::import("sys").attr("stderr"));
+ py::scoped_ostream_redirect redirout(std::cout, py::module_::import("sys").attr("stdout"));
+ py::scoped_ostream_redirect redirerr(std::cerr, py::module_::import("sys").attr("stderr"));
std::cout << msg << std::flush;
std::cerr << emsg << std::flush;
});
diff --git a/3rdparty/pybind11/tests/test_iostream.py b/3rdparty/pybind11/tests/test_iostream.py
index 27095b27..506db42e 100644
--- a/3rdparty/pybind11/tests/test_iostream.py
+++ b/3rdparty/pybind11/tests/test_iostream.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from pybind11_tests import iostream as m
import sys
@@ -17,6 +18,7 @@ try:
# Python 3.4
from contextlib import redirect_stdout
except ImportError:
+
@contextmanager
def redirect_stdout(target):
original = sys.stdout
@@ -24,10 +26,12 @@ except ImportError:
yield
sys.stdout = original
+
try:
# Python 3.5
from contextlib import redirect_stderr
except ImportError:
+
@contextmanager
def redirect_stderr(target):
original = sys.stderr
@@ -41,16 +45,16 @@ def test_captured(capsys):
m.captured_output(msg)
stdout, stderr = capsys.readouterr()
assert stdout == msg
- assert stderr == ''
+ assert stderr == ""
m.captured_output_default(msg)
stdout, stderr = capsys.readouterr()
assert stdout == msg
- assert stderr == ''
+ assert stderr == ""
m.captured_err(msg)
stdout, stderr = capsys.readouterr()
- assert stdout == ''
+ assert stdout == ""
assert stderr == msg
@@ -62,7 +66,7 @@ def test_captured_large_string(capsys):
m.captured_output_default(msg)
stdout, stderr = capsys.readouterr()
assert stdout == msg
- assert stderr == ''
+ assert stderr == ""
def test_guard_capture(capsys):
@@ -70,7 +74,7 @@ def test_guard_capture(capsys):
m.guard_output(msg)
stdout, stderr = capsys.readouterr()
assert stdout == msg
- assert stderr == ''
+ assert stderr == ""
def test_series_captured(capture):
@@ -87,7 +91,7 @@ def test_flush(capfd):
with m.ostream_redirect():
m.noisy_function(msg, flush=False)
stdout, stderr = capfd.readouterr()
- assert stdout == ''
+ assert stdout == ""
m.noisy_function(msg2, flush=True)
stdout, stderr = capfd.readouterr()
@@ -106,15 +110,15 @@ def test_not_captured(capfd):
m.raw_output(msg)
stdout, stderr = capfd.readouterr()
assert stdout == msg
- assert stderr == ''
- assert stream.getvalue() == ''
+ assert stderr == ""
+ assert stream.getvalue() == ""
stream = StringIO()
with redirect_stdout(stream):
m.captured_output(msg)
stdout, stderr = capfd.readouterr()
- assert stdout == ''
- assert stderr == ''
+ assert stdout == ""
+ assert stderr == ""
assert stream.getvalue() == msg
@@ -124,16 +128,16 @@ def test_err(capfd):
with redirect_stderr(stream):
m.raw_err(msg)
stdout, stderr = capfd.readouterr()
- assert stdout == ''
+ assert stdout == ""
assert stderr == msg
- assert stream.getvalue() == ''
+ assert stream.getvalue() == ""
stream = StringIO()
with redirect_stderr(stream):
m.captured_err(msg)
stdout, stderr = capfd.readouterr()
- assert stdout == ''
- assert stderr == ''
+ assert stdout == ""
+ assert stderr == ""
assert stream.getvalue() == msg
@@ -145,8 +149,8 @@ def test_multi_captured(capfd):
m.captured_output("c")
m.raw_output("d")
stdout, stderr = capfd.readouterr()
- assert stdout == 'bd'
- assert stream.getvalue() == 'ac'
+ assert stdout == "bd"
+ assert stream.getvalue() == "ac"
def test_dual(capsys):
@@ -163,14 +167,14 @@ def test_redirect(capfd):
m.raw_output(msg)
stdout, stderr = capfd.readouterr()
assert stdout == msg
- assert stream.getvalue() == ''
+ assert stream.getvalue() == ""
stream = StringIO()
with redirect_stdout(stream):
with m.ostream_redirect():
m.raw_output(msg)
stdout, stderr = capfd.readouterr()
- assert stdout == ''
+ assert stdout == ""
assert stream.getvalue() == msg
stream = StringIO()
@@ -178,7 +182,7 @@ def test_redirect(capfd):
m.raw_output(msg)
stdout, stderr = capfd.readouterr()
assert stdout == msg
- assert stream.getvalue() == ''
+ assert stream.getvalue() == ""
def test_redirect_err(capfd):
@@ -192,7 +196,7 @@ def test_redirect_err(capfd):
m.raw_err(msg2)
stdout, stderr = capfd.readouterr()
assert stdout == msg
- assert stderr == ''
+ assert stderr == ""
assert stream.getvalue() == msg2
@@ -208,7 +212,7 @@ def test_redirect_both(capfd):
m.raw_output(msg)
m.raw_err(msg2)
stdout, stderr = capfd.readouterr()
- assert stdout == ''
- assert stderr == ''
+ assert stdout == ""
+ assert stderr == ""
assert stream.getvalue() == msg
assert stream2.getvalue() == msg2
diff --git a/3rdparty/pybind11/tests/test_kwargs_and_defaults.cpp b/3rdparty/pybind11/tests/test_kwargs_and_defaults.cpp
index 6563fb9a..627a7969 100644
--- a/3rdparty/pybind11/tests/test_kwargs_and_defaults.cpp
+++ b/3rdparty/pybind11/tests/test_kwargs_and_defaults.cpp
@@ -71,7 +71,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
py::tuple t(a.size());
for (size_t i = 0; i < a.size(); i++)
// Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
- t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<ssize_t>(i)));
+ t[i] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
return t;
});
m.def("mixed_args_refcount", [](py::object o, py::args a) {
@@ -80,7 +80,7 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
t[0] = o.ref_count();
for (size_t i = 0; i < a.size(); i++)
// Use raw Python API here to avoid an extra, intermediate incref on the tuple item:
- t[i + 1] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<ssize_t>(i)));
+ t[i + 1] = (int) Py_REFCNT(PyTuple_GET_ITEM(a.ptr(), static_cast<py::ssize_t>(i)));
return t;
});
@@ -94,9 +94,49 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
// m.def("bad_args6", [](py::args, py::args) {});
// m.def("bad_args7", [](py::kwargs, py::kwargs) {});
+ // test_keyword_only_args
+ m.def("kw_only_all", [](int i, int j) { return py::make_tuple(i, j); },
+ py::kw_only(), py::arg("i"), py::arg("j"));
+ m.def("kw_only_some", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
+ py::arg(), py::kw_only(), py::arg("j"), py::arg("k"));
+ m.def("kw_only_with_defaults", [](int i, int j, int k, int z) { return py::make_tuple(i, j, k, z); },
+ py::arg() = 3, "j"_a = 4, py::kw_only(), "k"_a = 5, "z"_a);
+ m.def("kw_only_mixed", [](int i, int j) { return py::make_tuple(i, j); },
+ "i"_a, py::kw_only(), "j"_a);
+ m.def("kw_only_plus_more", [](int i, int j, int k, py::kwargs kwargs) {
+ return py::make_tuple(i, j, k, kwargs); },
+ py::arg() /* positional */, py::arg("j") = -1 /* both */, py::kw_only(), py::arg("k") /* kw-only */);
+
+ m.def("register_invalid_kw_only", [](py::module_ m) {
+ m.def("bad_kw_only", [](int i, int j) { return py::make_tuple(i, j); },
+ py::kw_only(), py::arg() /* invalid unnamed argument */, "j"_a);
+ });
+
+ // test_positional_only_args
+ m.def("pos_only_all", [](int i, int j) { return py::make_tuple(i, j); },
+ py::arg("i"), py::arg("j"), py::pos_only());
+ m.def("pos_only_mix", [](int i, int j) { return py::make_tuple(i, j); },
+ py::arg("i"), py::pos_only(), py::arg("j"));
+ m.def("pos_kw_only_mix", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
+ py::arg("i"), py::pos_only(), py::arg("j"), py::kw_only(), py::arg("k"));
+ m.def("pos_only_def_mix", [](int i, int j, int k) { return py::make_tuple(i, j, k); },
+ py::arg("i"), py::arg("j") = 2, py::pos_only(), py::arg("k") = 3);
+
+
+ // These should fail to compile:
+ // argument annotations are required when using kw_only
+// m.def("bad_kw_only1", [](int) {}, py::kw_only());
+ // can't specify both `py::kw_only` and a `py::args` argument
+// m.def("bad_kw_only2", [](int i, py::args) {}, py::kw_only(), "i"_a);
+
// test_function_signatures (along with most of the above)
struct KWClass { void foo(int, float) {} };
py::class_<KWClass>(m, "KWClass")
.def("foo0", &KWClass::foo)
.def("foo1", &KWClass::foo, "x"_a, "y"_a);
+
+ // Make sure a class (not an instance) can be used as a default argument.
+ // The return value doesn't matter, only that the module is importable.
+ m.def("class_default_argument", [](py::object a) { return py::repr(a); },
+ "a"_a = py::module_::import("decimal").attr("Decimal"));
}
diff --git a/3rdparty/pybind11/tests/test_kwargs_and_defaults.py b/3rdparty/pybind11/tests/test_kwargs_and_defaults.py
index 27a05a02..12fe705b 100644
--- a/3rdparty/pybind11/tests/test_kwargs_and_defaults.py
+++ b/3rdparty/pybind11/tests/test_kwargs_and_defaults.py
@@ -1,4 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
+
+import env # noqa: F401
+
from pybind11_tests import kwargs_and_defaults as m
@@ -11,11 +15,17 @@ def test_function_signatures(doc):
assert doc(m.kw_func_udl) == "kw_func_udl(x: int, y: int = 300) -> str"
assert doc(m.kw_func_udl_z) == "kw_func_udl_z(x: int, y: int = 0) -> str"
assert doc(m.args_function) == "args_function(*args) -> tuple"
- assert doc(m.args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple"
- assert doc(m.KWClass.foo0) == \
- "foo0(self: m.kwargs_and_defaults.KWClass, arg0: int, arg1: float) -> None"
- assert doc(m.KWClass.foo1) == \
- "foo1(self: m.kwargs_and_defaults.KWClass, x: int, y: float) -> None"
+ assert (
+ doc(m.args_kwargs_function) == "args_kwargs_function(*args, **kwargs) -> tuple"
+ )
+ assert (
+ doc(m.KWClass.foo0)
+ == "foo0(self: m.kwargs_and_defaults.KWClass, arg0: int, arg1: float) -> None"
+ )
+ assert (
+ doc(m.KWClass.foo1)
+ == "foo1(self: m.kwargs_and_defaults.KWClass, x: int, y: float) -> None"
+ )
def test_named_arguments(msg):
@@ -36,7 +46,9 @@ def test_named_arguments(msg):
# noinspection PyArgumentList
m.kw_func2(x=5, y=10, z=12)
assert excinfo.match(
- r'(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))' + '{3}$')
+ r"(?s)^kw_func2\(\): incompatible.*Invoked with: kwargs: ((x=5|y=10|z=12)(, |$))"
+ + "{3}$"
+ )
assert m.kw_func4() == "{13 17}"
assert m.kw_func4(myList=[1, 2, 3]) == "{1 2 3}"
@@ -46,11 +58,11 @@ def test_named_arguments(msg):
def test_arg_and_kwargs():
- args = 'arg1_value', 'arg2_value', 3
+ args = "arg1_value", "arg2_value", 3
assert m.args_function(*args) == args
- args = 'a1', 'a2'
- kwargs = dict(arg3='a3', arg4=4)
+ args = "a1", "a2"
+ kwargs = dict(arg3="a3", arg4=4)
assert m.args_kwargs_function(*args, **kwargs) == (args, kwargs)
@@ -64,49 +76,166 @@ def test_mixed_args_and_kwargs(msg):
assert mpa(1, 2.5) == (1, 2.5, ())
with pytest.raises(TypeError) as excinfo:
assert mpa(1)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
mixed_plus_args(): incompatible function arguments. The following argument types are supported:
1. (arg0: int, arg1: float, *args) -> tuple
Invoked with: 1
""" # noqa: E501 line too long
+ )
with pytest.raises(TypeError) as excinfo:
assert mpa()
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
mixed_plus_args(): incompatible function arguments. The following argument types are supported:
1. (arg0: int, arg1: float, *args) -> tuple
Invoked with:
""" # noqa: E501 line too long
+ )
- assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == (-2, 3.5, {'e': 2.71828, 'pi': 3.14159})
+ assert mpk(-2, 3.5, pi=3.14159, e=2.71828) == (
+ -2,
+ 3.5,
+ {"e": 2.71828, "pi": 3.14159},
+ )
assert mpak(7, 7.7, 7.77, 7.777, 7.7777, minusseven=-7) == (
- 7, 7.7, (7.77, 7.777, 7.7777), {'minusseven': -7})
+ 7,
+ 7.7,
+ (7.77, 7.777, 7.7777),
+ {"minusseven": -7},
+ )
assert mpakd() == (1, 3.14159, (), {})
assert mpakd(3) == (3, 3.14159, (), {})
assert mpakd(j=2.71828) == (1, 2.71828, (), {})
- assert mpakd(k=42) == (1, 3.14159, (), {'k': 42})
+ assert mpakd(k=42) == (1, 3.14159, (), {"k": 42})
assert mpakd(1, 1, 2, 3, 5, 8, then=13, followedby=21) == (
- 1, 1, (2, 3, 5, 8), {'then': 13, 'followedby': 21})
+ 1,
+ 1,
+ (2, 3, 5, 8),
+ {"then": 13, "followedby": 21},
+ )
# Arguments specified both positionally and via kwargs should fail:
with pytest.raises(TypeError) as excinfo:
assert mpakd(1, i=1)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
mixed_plus_args_kwargs_defaults(): incompatible function arguments. The following argument types are supported:
1. (i: int = 1, j: float = 3.14159, *args, **kwargs) -> tuple
Invoked with: 1; kwargs: i=1
""" # noqa: E501 line too long
+ )
with pytest.raises(TypeError) as excinfo:
assert mpakd(1, 2, j=1)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
mixed_plus_args_kwargs_defaults(): incompatible function arguments. The following argument types are supported:
1. (i: int = 1, j: float = 3.14159, *args, **kwargs) -> tuple
Invoked with: 1, 2; kwargs: j=1
""" # noqa: E501 line too long
+ )
+
+
+def test_keyword_only_args(msg):
+ assert m.kw_only_all(i=1, j=2) == (1, 2)
+ assert m.kw_only_all(j=1, i=2) == (2, 1)
+
+ with pytest.raises(TypeError) as excinfo:
+ assert m.kw_only_all(i=1) == (1,)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ with pytest.raises(TypeError) as excinfo:
+ assert m.kw_only_all(1, 2) == (1, 2)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ assert m.kw_only_some(1, k=3, j=2) == (1, 2, 3)
+ assert m.kw_only_with_defaults(z=8) == (3, 4, 5, 8)
+ assert m.kw_only_with_defaults(2, z=8) == (2, 4, 5, 8)
+ assert m.kw_only_with_defaults(2, j=7, k=8, z=9) == (2, 7, 8, 9)
+ assert m.kw_only_with_defaults(2, 7, z=9, k=8) == (2, 7, 8, 9)
+
+ assert m.kw_only_mixed(1, j=2) == (1, 2)
+ assert m.kw_only_mixed(j=2, i=3) == (3, 2)
+ assert m.kw_only_mixed(i=2, j=3) == (2, 3)
+
+ assert m.kw_only_plus_more(4, 5, k=6, extra=7) == (4, 5, 6, {"extra": 7})
+ assert m.kw_only_plus_more(3, k=5, j=4, extra=6) == (3, 4, 5, {"extra": 6})
+ assert m.kw_only_plus_more(2, k=3, extra=4) == (2, -1, 3, {"extra": 4})
+
+ with pytest.raises(TypeError) as excinfo:
+ assert m.kw_only_mixed(i=1) == (1,)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ with pytest.raises(RuntimeError) as excinfo:
+ m.register_invalid_kw_only(m)
+ assert (
+ msg(excinfo.value)
+ == """
+ arg(): cannot specify an unnamed argument after an kw_only() annotation
+ """
+ )
+
+
+def test_positional_only_args(msg):
+ assert m.pos_only_all(1, 2) == (1, 2)
+ assert m.pos_only_all(2, 1) == (2, 1)
+
+ with pytest.raises(TypeError) as excinfo:
+ m.pos_only_all(i=1, j=2)
+ assert "incompatible function arguments" in str(excinfo.value)
+ assert m.pos_only_mix(1, 2) == (1, 2)
+ assert m.pos_only_mix(2, j=1) == (2, 1)
+
+ with pytest.raises(TypeError) as excinfo:
+ m.pos_only_mix(i=1, j=2)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ assert m.pos_kw_only_mix(1, 2, k=3) == (1, 2, 3)
+ assert m.pos_kw_only_mix(1, j=2, k=3) == (1, 2, 3)
+
+ with pytest.raises(TypeError) as excinfo:
+ m.pos_kw_only_mix(i=1, j=2, k=3)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ with pytest.raises(TypeError) as excinfo:
+ m.pos_kw_only_mix(1, 2, 3)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ with pytest.raises(TypeError) as excinfo:
+ m.pos_only_def_mix()
+ assert "incompatible function arguments" in str(excinfo.value)
+
+ assert m.pos_only_def_mix(1) == (1, 2, 3)
+ assert m.pos_only_def_mix(1, 4) == (1, 4, 3)
+ assert m.pos_only_def_mix(1, 4, 7) == (1, 4, 7)
+ assert m.pos_only_def_mix(1, 4, k=7) == (1, 4, 7)
+
+ with pytest.raises(TypeError) as excinfo:
+ m.pos_only_def_mix(1, j=4)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+
+def test_signatures():
+ assert "kw_only_all(*, i: int, j: int) -> tuple\n" == m.kw_only_all.__doc__
+ assert "kw_only_mixed(i: int, *, j: int) -> tuple\n" == m.kw_only_mixed.__doc__
+ assert "pos_only_all(i: int, j: int, /) -> tuple\n" == m.pos_only_all.__doc__
+ assert "pos_only_mix(i: int, /, j: int) -> tuple\n" == m.pos_only_mix.__doc__
+ assert (
+ "pos_kw_only_mix(i: int, /, j: int, *, k: int) -> tuple\n"
+ == m.pos_kw_only_mix.__doc__
+ )
+
+
+@pytest.mark.xfail("env.PYPY and env.PY2", reason="PyPy2 doesn't double count")
def test_args_refcount():
"""Issue/PR #1216 - py::args elements get double-inc_ref()ed when combined with regular
arguments"""
@@ -128,11 +257,18 @@ def test_args_refcount():
assert m.args_function(-1, myval) == (-1, myval)
assert refcount(myval) == expected
- assert m.mixed_plus_args_kwargs(5, 6.0, myval, a=myval) == (5, 6.0, (myval,), {"a": myval})
+ assert m.mixed_plus_args_kwargs(5, 6.0, myval, a=myval) == (
+ 5,
+ 6.0,
+ (myval,),
+ {"a": myval},
+ )
assert refcount(myval) == expected
- assert m.args_kwargs_function(7, 8, myval, a=1, b=myval) == \
- ((7, 8, myval), {"a": 1, "b": myval})
+ assert m.args_kwargs_function(7, 8, myval, a=1, b=myval) == (
+ (7, 8, myval),
+ {"a": 1, "b": myval},
+ )
assert refcount(myval) == expected
exp3 = refcount(myval, myval, myval)
@@ -145,3 +281,5 @@ def test_args_refcount():
# tuple without having to inc_ref the individual elements, but here we can't, hence the extra
# refs.
assert m.mixed_args_refcount(myval, myval, myval) == (exp3 + 3, exp3 + 3, exp3 + 3)
+
+ assert m.class_default_argument() == "<class 'decimal.Decimal'>"
diff --git a/3rdparty/pybind11/tests/test_local_bindings.cpp b/3rdparty/pybind11/tests/test_local_bindings.cpp
index 97c02dbe..c61e3888 100644
--- a/3rdparty/pybind11/tests/test_local_bindings.cpp
+++ b/3rdparty/pybind11/tests/test_local_bindings.cpp
@@ -41,7 +41,7 @@ TEST_SUBMODULE(local_bindings, m) {
// should raise a runtime error from the duplicate definition attempt. If test_class isn't
// available it *also* throws a runtime error (with "test_class not enabled" as value).
m.def("register_local_external", [m]() {
- auto main = py::module::import("pybind11_tests");
+ auto main = py::module_::import("pybind11_tests");
if (py::hasattr(main, "class_")) {
bind_local<LocalExternal, 7>(m, "LocalExternal", py::module_local());
}
diff --git a/3rdparty/pybind11/tests/test_local_bindings.py b/3rdparty/pybind11/tests/test_local_bindings.py
index b380376e..d23c4675 100644
--- a/3rdparty/pybind11/tests/test_local_bindings.py
+++ b/3rdparty/pybind11/tests/test_local_bindings.py
@@ -1,5 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
+import env # noqa: F401
+
from pybind11_tests import local_bindings as m
@@ -33,8 +36,8 @@ def test_local_bindings():
assert i2.get() == 11
assert i2.get2() == 12
- assert not hasattr(i1, 'get2')
- assert not hasattr(i2, 'get3')
+ assert not hasattr(i1, "get2")
+ assert not hasattr(i2, "get3")
# Loading within the local module
assert m.local_value(i1) == 5
@@ -52,7 +55,9 @@ def test_nonlocal_failure():
with pytest.raises(RuntimeError) as excinfo:
cm.register_nonlocal()
- assert str(excinfo.value) == 'generic_type: type "NonLocalType" is already registered!'
+ assert (
+ str(excinfo.value) == 'generic_type: type "NonLocalType" is already registered!'
+ )
def test_duplicate_local():
@@ -60,9 +65,12 @@ def test_duplicate_local():
with pytest.raises(RuntimeError) as excinfo:
m.register_local_external()
import pybind11_tests
+
assert str(excinfo.value) == (
'generic_type: type "LocalExternal" is already registered!'
- if hasattr(pybind11_tests, 'class_') else 'test_class not enabled')
+ if hasattr(pybind11_tests, "class_")
+ else "test_class not enabled"
+ )
def test_stl_bind_local():
@@ -95,8 +103,8 @@ def test_stl_bind_local():
d1["b"] = v1[1]
d2["c"] = v2[0]
d2["d"] = v2[1]
- assert {i: d1[i].get() for i in d1} == {'a': 0, 'b': 1}
- assert {i: d2[i].get() for i in d2} == {'c': 2, 'd': 3}
+ assert {i: d1[i].get() for i in d1} == {"a": 0, "b": 1}
+ assert {i: d2[i].get() for i in d2} == {"c": 2, "d": 3}
def test_stl_bind_global():
@@ -104,15 +112,21 @@ def test_stl_bind_global():
with pytest.raises(RuntimeError) as excinfo:
cm.register_nonlocal_map()
- assert str(excinfo.value) == 'generic_type: type "NonLocalMap" is already registered!'
+ assert (
+ str(excinfo.value) == 'generic_type: type "NonLocalMap" is already registered!'
+ )
with pytest.raises(RuntimeError) as excinfo:
cm.register_nonlocal_vec()
- assert str(excinfo.value) == 'generic_type: type "NonLocalVec" is already registered!'
+ assert (
+ str(excinfo.value) == 'generic_type: type "NonLocalVec" is already registered!'
+ )
with pytest.raises(RuntimeError) as excinfo:
cm.register_nonlocal_map2()
- assert str(excinfo.value) == 'generic_type: type "NonLocalMap2" is already registered!'
+ assert (
+ str(excinfo.value) == 'generic_type: type "NonLocalMap2" is already registered!'
+ )
def test_mixed_local_global():
@@ -120,6 +134,7 @@ def test_mixed_local_global():
type can be registered even if the type is already registered globally. With the module,
casting will go to the local type; outside the module casting goes to the global type."""
import pybind11_cross_module_tests as cm
+
m.register_mixed_global()
m.register_mixed_local()
@@ -142,16 +157,30 @@ def test_mixed_local_global():
a.append(cm.get_mixed_gl(11))
a.append(cm.get_mixed_lg(12))
- assert [x.get() for x in a] == \
- [101, 1002, 103, 1004, 105, 1006, 207, 2008, 109, 1010, 211, 2012]
+ assert [x.get() for x in a] == [
+ 101,
+ 1002,
+ 103,
+ 1004,
+ 105,
+ 1006,
+ 207,
+ 2008,
+ 109,
+ 1010,
+ 211,
+ 2012,
+ ]
def test_internal_locals_differ():
"""Makes sure the internal local type map differs across the two modules"""
import pybind11_cross_module_tests as cm
+
assert m.local_cpp_types_addr() != cm.local_cpp_types_addr()
+@pytest.mark.xfail("env.PYPY and sys.pypy_version_info < (7, 3, 2)")
def test_stl_caster_vs_stl_bind(msg):
"""One module uses a generic vector caster from `<pybind11/stl.h>` while the other
exports `std::vector<int>` via `py:bind_vector` and `py::module_local`"""
@@ -165,12 +194,15 @@ def test_stl_caster_vs_stl_bind(msg):
assert m.load_vector_via_caster(v2) == 6
with pytest.raises(TypeError) as excinfo:
cm.load_vector_via_binding(v2) == 6
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
load_vector_via_binding(): incompatible function arguments. The following argument types are supported:
1. (arg0: pybind11_cross_module_tests.VectorInt) -> int
Invoked with: [1, 2, 3]
""" # noqa: E501 line too long
+ )
def test_cross_module_calls():
diff --git a/3rdparty/pybind11/tests/test_methods_and_attributes.cpp b/3rdparty/pybind11/tests/test_methods_and_attributes.cpp
index c7b82f13..6a2cfb6f 100644
--- a/3rdparty/pybind11/tests/test_methods_and_attributes.cpp
+++ b/3rdparty/pybind11/tests/test_methods_and_attributes.cpp
@@ -21,6 +21,7 @@ public:
ExampleMandA() { print_default_created(this); }
ExampleMandA(int value) : value(value) { print_created(this, value); }
ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); }
+ ExampleMandA(std::string&&) {}
ExampleMandA(ExampleMandA &&e) : value(e.value) { print_move_created(this); }
~ExampleMandA() { print_destroyed(this); }
@@ -43,6 +44,8 @@ public:
void add9(int *other) { value += *other; } // passing by pointer
void add10(const int *other) { value += *other; } // passing by const pointer
+ void consume_str(std::string&&) {}
+
ExampleMandA self1() { return *this; } // return by value
ExampleMandA &self2() { return *this; } // return by reference
const ExampleMandA &self3() { return *this; } // return by const reference
@@ -105,76 +108,6 @@ struct TestPropRVP {
UserType TestPropRVP::sv1(1);
UserType TestPropRVP::sv2(1);
-// py::arg/py::arg_v testing: these arguments just record their argument when invoked
-class ArgInspector1 { public: std::string arg = "(default arg inspector 1)"; };
-class ArgInspector2 { public: std::string arg = "(default arg inspector 2)"; };
-class ArgAlwaysConverts { };
-namespace pybind11 { namespace detail {
-template <> struct type_caster<ArgInspector1> {
-public:
- PYBIND11_TYPE_CASTER(ArgInspector1, _("ArgInspector1"));
-
- bool load(handle src, bool convert) {
- value.arg = "loading ArgInspector1 argument " +
- std::string(convert ? "WITH" : "WITHOUT") + " conversion allowed. "
- "Argument value = " + (std::string) str(src);
- return true;
- }
-
- static handle cast(const ArgInspector1 &src, return_value_policy, handle) {
- return str(src.arg).release();
- }
-};
-template <> struct type_caster<ArgInspector2> {
-public:
- PYBIND11_TYPE_CASTER(ArgInspector2, _("ArgInspector2"));
-
- bool load(handle src, bool convert) {
- value.arg = "loading ArgInspector2 argument " +
- std::string(convert ? "WITH" : "WITHOUT") + " conversion allowed. "
- "Argument value = " + (std::string) str(src);
- return true;
- }
-
- static handle cast(const ArgInspector2 &src, return_value_policy, handle) {
- return str(src.arg).release();
- }
-};
-template <> struct type_caster<ArgAlwaysConverts> {
-public:
- PYBIND11_TYPE_CASTER(ArgAlwaysConverts, _("ArgAlwaysConverts"));
-
- bool load(handle, bool convert) {
- return convert;
- }
-
- static handle cast(const ArgAlwaysConverts &, return_value_policy, handle) {
- return py::none().release();
- }
-};
-}}
-
-// test_custom_caster_destruction
-class DestructionTester {
-public:
- DestructionTester() { print_default_created(this); }
- ~DestructionTester() { print_destroyed(this); }
- DestructionTester(const DestructionTester &) { print_copy_created(this); }
- DestructionTester(DestructionTester &&) { print_move_created(this); }
- DestructionTester &operator=(const DestructionTester &) { print_copy_assigned(this); return *this; }
- DestructionTester &operator=(DestructionTester &&) { print_move_assigned(this); return *this; }
-};
-namespace pybind11 { namespace detail {
-template <> struct type_caster<DestructionTester> {
- PYBIND11_TYPE_CASTER(DestructionTester, _("DestructionTester"));
- bool load(handle, bool) { return true; }
-
- static handle cast(const DestructionTester &, return_value_policy, handle) {
- return py::bool_(true).release();
- }
-};
-}}
-
// Test None-allowed py::arg argument policy
class NoneTester { public: int answer = 42; };
int none1(const NoneTester &obj) { return obj.answer; }
@@ -207,11 +140,20 @@ public:
double sum() const { return rw_value + ro_value; }
};
+// Test explicit lvalue ref-qualification
+struct RefQualified {
+ int value = 0;
+
+ void refQualified(int other) & { value += other; }
+ int constRefQualified(int other) const & { return value + other; }
+};
+
TEST_SUBMODULE(methods_and_attributes, m) {
// test_methods_and_attributes
py::class_<ExampleMandA> emna(m, "ExampleMandA");
emna.def(py::init<>())
.def(py::init<int>())
+ .def(py::init<std::string&&>())
.def(py::init<const ExampleMandA&>())
.def("add1", &ExampleMandA::add1)
.def("add2", &ExampleMandA::add2)
@@ -223,6 +165,7 @@ TEST_SUBMODULE(methods_and_attributes, m) {
.def("add8", &ExampleMandA::add8)
.def("add9", &ExampleMandA::add9)
.def("add10", &ExampleMandA::add10)
+ .def("consume_str", &ExampleMandA::consume_str)
.def("self1", &ExampleMandA::self1)
.def("self2", &ExampleMandA::self2)
.def("self3", &ExampleMandA::self3)
@@ -264,12 +207,12 @@ TEST_SUBMODULE(methods_and_attributes, m) {
// test_no_mixed_overloads
// Raise error if trying to mix static/non-static overloads on the same name:
.def_static("add_mixed_overloads1", []() {
- auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
+ auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module_::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
emna.def ("overload_mixed1", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded))
.def_static("overload_mixed1", static_cast<py::str ( *)(float )>(&ExampleMandA::overloaded));
})
.def_static("add_mixed_overloads2", []() {
- auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
+ auto emna = py::reinterpret_borrow<py::class_<ExampleMandA>>(py::module_::import("pybind11_tests.methods_and_attributes").attr("ExampleMandA"));
emna.def_static("overload_mixed2", static_cast<py::str ( *)(float )>(&ExampleMandA::overloaded))
.def ("overload_mixed2", static_cast<py::str (ExampleMandA::*)(int, int)>(&ExampleMandA::overloaded));
})
@@ -341,11 +284,18 @@ TEST_SUBMODULE(methods_and_attributes, m) {
py::class_<MetaclassOverride>(m, "MetaclassOverride", py::metaclass((PyObject *) &PyType_Type))
.def_property_readonly_static("readonly", [](py::object) { return 1; });
+ // test_overload_ordering
+ m.def("overload_order", [](std::string) { return 1; });
+ m.def("overload_order", [](std::string) { return 2; });
+ m.def("overload_order", [](int) { return 3; });
+ m.def("overload_order", [](int) { return 4; }, py::prepend{});
+
#if !defined(PYPY_VERSION)
// test_dynamic_attributes
class DynamicClass {
public:
DynamicClass() { print_default_created(this); }
+ DynamicClass(const DynamicClass&) = delete;
~DynamicClass() { print_destroyed(this); }
};
py::class_<DynamicClass>(m, "DynamicClass", py::dynamic_attr())
@@ -356,33 +306,6 @@ TEST_SUBMODULE(methods_and_attributes, m) {
.def(py::init());
#endif
- // test_noconvert_args
- //
- // Test converting. The ArgAlwaysConverts is just there to make the first no-conversion pass
- // fail so that our call always ends up happening via the second dispatch (the one that allows
- // some conversion).
- class ArgInspector {
- public:
- ArgInspector1 f(ArgInspector1 a, ArgAlwaysConverts) { return a; }
- std::string g(ArgInspector1 a, const ArgInspector1 &b, int c, ArgInspector2 *d, ArgAlwaysConverts) {
- return a.arg + "\n" + b.arg + "\n" + std::to_string(c) + "\n" + d->arg;
- }
- static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
- };
- py::class_<ArgInspector>(m, "ArgInspector")
- .def(py::init<>())
- .def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
- .def("g", &ArgInspector::g, "a"_a.noconvert(), "b"_a, "c"_a.noconvert()=13, "d"_a=ArgInspector2(), py::arg() = ArgAlwaysConverts())
- .def_static("h", &ArgInspector::h, py::arg().noconvert(), py::arg() = ArgAlwaysConverts())
- ;
- m.def("arg_inspect_func", [](ArgInspector2 a, ArgInspector1 b, ArgAlwaysConverts) { return a.arg + "\n" + b.arg; },
- py::arg().noconvert(false), py::arg_v(nullptr, ArgInspector1()).noconvert(true), py::arg() = ArgAlwaysConverts());
-
- m.def("floats_preferred", [](double f) { return 0.5 * f; }, py::arg("f"));
- m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());
- m.def("ints_preferred", [](int i) { return i / 2; }, py::arg("i"));
- m.def("ints_only", [](int i) { return i / 2; }, py::arg("i").noconvert());
-
// test_bad_arg_default
// Issue/PR #648: bad arg default debugging output
#if !defined(NDEBUG)
@@ -391,11 +314,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
m.attr("debug_enabled") = false;
#endif
m.def("bad_arg_def_named", []{
- auto m = py::module::import("pybind11_tests");
+ auto m = py::module_::import("pybind11_tests");
m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg("a") = UnregisteredType());
});
m.def("bad_arg_def_unnamed", []{
- auto m = py::module::import("pybind11_tests");
+ auto m = py::module_::import("pybind11_tests");
m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg() = UnregisteredType());
});
@@ -413,6 +336,9 @@ TEST_SUBMODULE(methods_and_attributes, m) {
m.def("ok_none4", &none4, py::arg().none(true));
m.def("ok_none5", &none5);
+ m.def("no_none_kwarg", &none2, py::arg("a").none(false));
+ m.def("no_none_kwarg_kw_only", &none2, py::kw_only(), py::arg("a").none(false));
+
// test_str_issue
// Issue #283: __str__ called on uninitialized instance when constructor arguments invalid
py::class_<StrIssue>(m, "StrIssue")
@@ -446,15 +372,10 @@ TEST_SUBMODULE(methods_and_attributes, m) {
using Adapted = decltype(py::method_adaptor<RegisteredDerived>(&RegisteredDerived::do_nothing));
static_assert(std::is_same<Adapted, void (RegisteredDerived::*)() const>::value, "");
- // test_custom_caster_destruction
- // Test that `take_ownership` works on types with a custom type caster when given a pointer
-
- // default policy: don't take ownership:
- m.def("custom_caster_no_destroy", []() { static auto *dt = new DestructionTester(); return dt; });
-
- m.def("custom_caster_destroy", []() { return new DestructionTester(); },
- py::return_value_policy::take_ownership); // Takes ownership: destroy when finished
- m.def("custom_caster_destroy_const", []() -> const DestructionTester * { return new DestructionTester(); },
- py::return_value_policy::take_ownership); // Likewise (const doesn't inhibit destruction)
- m.def("destruction_tester_cstats", &ConstructorStats::get<DestructionTester>, py::return_value_policy::reference);
+ // test_methods_and_attributes
+ py::class_<RefQualified>(m, "RefQualified")
+ .def(py::init<>())
+ .def_readonly("value", &RefQualified::value)
+ .def("refQualified", &RefQualified::refQualified)
+ .def("constRefQualified", &RefQualified::constRefQualified);
}
diff --git a/3rdparty/pybind11/tests/test_methods_and_attributes.py b/3rdparty/pybind11/tests/test_methods_and_attributes.py
index f1c862be..2aaf9331 100644
--- a/3rdparty/pybind11/tests/test_methods_and_attributes.py
+++ b/3rdparty/pybind11/tests/test_methods_and_attributes.py
@@ -1,4 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
+
+import env # noqa: F401
+
from pybind11_tests import methods_and_attributes as m
from pybind11_tests import ConstructorStats
@@ -36,17 +40,17 @@ def test_methods_and_attributes():
assert instance1.overloaded(0) == "(int)"
assert instance1.overloaded(1, 1.0) == "(int, float)"
assert instance1.overloaded(2.0, 2) == "(float, int)"
- assert instance1.overloaded(3, 3) == "(int, int)"
- assert instance1.overloaded(4., 4.) == "(float, float)"
+ assert instance1.overloaded(3, 3) == "(int, int)"
+ assert instance1.overloaded(4.0, 4.0) == "(float, float)"
assert instance1.overloaded_const(-3) == "(int) const"
assert instance1.overloaded_const(5, 5.0) == "(int, float) const"
assert instance1.overloaded_const(6.0, 6) == "(float, int) const"
- assert instance1.overloaded_const(7, 7) == "(int, int) const"
- assert instance1.overloaded_const(8., 8.) == "(float, float) const"
+ assert instance1.overloaded_const(7, 7) == "(int, int) const"
+ assert instance1.overloaded_const(8.0, 8.0) == "(float, float) const"
assert instance1.overloaded_float(1, 1) == "(float, float)"
- assert instance1.overloaded_float(1, 1.) == "(float, float)"
- assert instance1.overloaded_float(1., 1) == "(float, float)"
- assert instance1.overloaded_float(1., 1.) == "(float, float)"
+ assert instance1.overloaded_float(1, 1.0) == "(float, float)"
+ assert instance1.overloaded_float(1.0, 1) == "(float, float)"
+ assert instance1.overloaded_float(1.0, 1.0) == "(float, float)"
assert instance1.value == 320
instance1.value = 100
@@ -58,8 +62,8 @@ def test_methods_and_attributes():
assert cstats.alive() == 0
assert cstats.values() == ["32"]
assert cstats.default_constructions == 1
- assert cstats.copy_constructions == 3
- assert cstats.move_constructions >= 1
+ assert cstats.copy_constructions == 2
+ assert cstats.move_constructions >= 2
assert cstats.copy_assignments == 0
assert cstats.move_assignments == 0
@@ -167,6 +171,19 @@ def test_static_properties():
assert m.TestPropertiesOverride().def_readonly == 99
assert m.TestPropertiesOverride.def_readonly_static == 99
+ # Only static attributes can be deleted
+ del m.TestPropertiesOverride.def_readonly_static
+ assert (
+ hasattr(m.TestPropertiesOverride, "def_readonly_static")
+ and m.TestPropertiesOverride.def_readonly_static
+ is m.TestProperties.def_readonly_static
+ )
+ assert "def_readonly_static" not in m.TestPropertiesOverride.__dict__
+ properties_override = m.TestPropertiesOverride()
+ with pytest.raises(AttributeError) as excinfo:
+ del properties_override.def_readonly
+ assert "can't delete attribute" in str(excinfo.value)
+
def test_static_cls():
"""Static property getter and setters expect the type object as the their only argument"""
@@ -189,7 +206,10 @@ def test_metaclass_override():
assert type(m.MetaclassOverride).__name__ == "type"
assert m.MetaclassOverride.readonly == 1
- assert type(m.MetaclassOverride.__dict__["readonly"]).__name__ == "pybind11_static_property"
+ assert (
+ type(m.MetaclassOverride.__dict__["readonly"]).__name__
+ == "pybind11_static_property"
+ )
# Regular `type` replaces the property instead of calling `__set__()`
m.MetaclassOverride.readonly = 2
@@ -202,22 +222,26 @@ def test_no_mixed_overloads():
with pytest.raises(RuntimeError) as excinfo:
m.ExampleMandA.add_mixed_overloads1()
- assert (str(excinfo.value) ==
- "overloading a method with both static and instance methods is not supported; " +
- ("compile in debug mode for more details" if not debug_enabled else
- "error while attempting to bind static method ExampleMandA.overload_mixed1"
- "(arg0: float) -> str")
- )
+ assert str(
+ excinfo.value
+ ) == "overloading a method with both static and instance methods is not supported; " + (
+ "compile in debug mode for more details"
+ if not debug_enabled
+ else "error while attempting to bind static method ExampleMandA.overload_mixed1"
+ "(arg0: float) -> str"
+ )
with pytest.raises(RuntimeError) as excinfo:
m.ExampleMandA.add_mixed_overloads2()
- assert (str(excinfo.value) ==
- "overloading a method with both static and instance methods is not supported; " +
- ("compile in debug mode for more details" if not debug_enabled else
- "error while attempting to bind instance method ExampleMandA.overload_mixed2"
- "(self: pybind11_tests.methods_and_attributes.ExampleMandA, arg0: int, arg1: int)"
- " -> str")
- )
+ assert str(
+ excinfo.value
+ ) == "overloading a method with both static and instance methods is not supported; " + (
+ "compile in debug mode for more details"
+ if not debug_enabled
+ else "error while attempting to bind instance method ExampleMandA.overload_mixed2"
+ "(self: pybind11_tests.methods_and_attributes.ExampleMandA, arg0: int, arg1: int)"
+ " -> str"
+ )
@pytest.mark.parametrize("access", ["ro", "rw", "static_ro", "static_rw"])
@@ -256,8 +280,8 @@ def test_property_rvalue_policy():
assert os.value == 1
-# https://bitbucket.org/pypy/pypy/issues/2447
-@pytest.unsupported_on_pypy
+# https://foss.heptapod.net/pypy/pypy/-/issues/2447
+@pytest.mark.xfail("env.PYPY")
def test_dynamic_attributes():
instance = m.DynamicClass()
assert not hasattr(instance, "foo")
@@ -298,8 +322,8 @@ def test_dynamic_attributes():
assert cstats.alive() == 0
-# https://bitbucket.org/pypy/pypy/issues/2447
-@pytest.unsupported_on_pypy
+# https://foss.heptapod.net/pypy/pypy/-/issues/2447
+@pytest.mark.xfail("env.PYPY")
def test_cyclic_gc():
# One object references itself
instance = m.DynamicClass()
@@ -321,69 +345,6 @@ def test_cyclic_gc():
assert cstats.alive() == 0
-def test_noconvert_args(msg):
- a = m.ArgInspector()
- assert msg(a.f("hi")) == """
- loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
- """
- assert msg(a.g("this is a", "this is b")) == """
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
- loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
- 13
- loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
- """ # noqa: E501 line too long
- assert msg(a.g("this is a", "this is b", 42)) == """
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
- loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
- 42
- loading ArgInspector2 argument WITH conversion allowed. Argument value = (default arg inspector 2)
- """ # noqa: E501 line too long
- assert msg(a.g("this is a", "this is b", 42, "this is d")) == """
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = this is a
- loading ArgInspector1 argument WITH conversion allowed. Argument value = this is b
- 42
- loading ArgInspector2 argument WITH conversion allowed. Argument value = this is d
- """
- assert (a.h("arg 1") ==
- "loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1")
- assert msg(m.arg_inspect_func("A1", "A2")) == """
- loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
- loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
- """
-
- assert m.floats_preferred(4) == 2.0
- assert m.floats_only(4.0) == 2.0
- with pytest.raises(TypeError) as excinfo:
- m.floats_only(4)
- assert msg(excinfo.value) == """
- floats_only(): incompatible function arguments. The following argument types are supported:
- 1. (f: float) -> float
-
- Invoked with: 4
- """
-
- assert m.ints_preferred(4) == 2
- assert m.ints_preferred(True) == 0
- with pytest.raises(TypeError) as excinfo:
- m.ints_preferred(4.0)
- assert msg(excinfo.value) == """
- ints_preferred(): incompatible function arguments. The following argument types are supported:
- 1. (i: int) -> int
-
- Invoked with: 4.0
- """ # noqa: E501 line too long
-
- assert m.ints_only(4) == 2
- with pytest.raises(TypeError) as excinfo:
- m.ints_only(4.0)
- assert msg(excinfo.value) == """
- ints_only(): incompatible function arguments. The following argument types are supported:
- 1. (i: int) -> int
-
- Invoked with: 4.0
- """
-
-
def test_bad_arg_default(msg):
from pybind11_tests import debug_enabled
@@ -392,8 +353,8 @@ def test_bad_arg_default(msg):
assert msg(excinfo.value) == (
"arg(): could not convert default argument 'a: UnregisteredType' in function "
"'should_fail' into a Python object (type not registered yet?)"
- if debug_enabled else
- "arg(): could not convert default argument into a Python object (type not registered "
+ if debug_enabled
+ else "arg(): could not convert default argument into a Python object (type not registered "
"yet?). Compile in debug mode for more information."
)
@@ -402,8 +363,8 @@ def test_bad_arg_default(msg):
assert msg(excinfo.value) == (
"arg(): could not convert default argument 'UnregisteredType' in function "
"'should_fail' into a Python object (type not registered yet?)"
- if debug_enabled else
- "arg(): could not convert default argument into a Python object (type not registered "
+ if debug_enabled
+ else "arg(): could not convert default argument into a Python object (type not registered "
"yet?). Compile in debug mode for more information."
)
@@ -440,12 +401,15 @@ def test_accepts_none(msg):
# The first one still raises because you can't pass None as a lvalue reference arg:
with pytest.raises(TypeError) as excinfo:
assert m.ok_none1(None) == -1
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
ok_none1(): incompatible function arguments. The following argument types are supported:
1. (arg0: m.methods_and_attributes.NoneTester) -> int
Invoked with: None
"""
+ )
# The rest take the argument as pointer or holder, and accept None:
assert m.ok_none2(None) == -1
@@ -453,6 +417,19 @@ def test_accepts_none(msg):
assert m.ok_none4(None) == -1
assert m.ok_none5(None) == -1
+ with pytest.raises(TypeError) as excinfo:
+ m.no_none_kwarg(None)
+ assert "incompatible function arguments" in str(excinfo.value)
+ with pytest.raises(TypeError) as excinfo:
+ m.no_none_kwarg(a=None)
+ assert "incompatible function arguments" in str(excinfo.value)
+ with pytest.raises(TypeError) as excinfo:
+ m.no_none_kwarg_kw_only(None)
+ assert "incompatible function arguments" in str(excinfo.value)
+ with pytest.raises(TypeError) as excinfo:
+ m.no_none_kwarg_kw_only(a=None)
+ assert "incompatible function arguments" in str(excinfo.value)
+
def test_str_issue(msg):
"""#283: __str__ called on uninitialized instance when constructor arguments invalid"""
@@ -461,13 +438,16 @@ def test_str_issue(msg):
with pytest.raises(TypeError) as excinfo:
str(m.StrIssue("no", "such", "constructor"))
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
__init__(): incompatible constructor arguments. The following argument types are supported:
1. m.methods_and_attributes.StrIssue(arg0: int)
2. m.methods_and_attributes.StrIssue()
Invoked with: 'no', 'such', 'constructor'
"""
+ )
def test_unregistered_base_implementations():
@@ -488,25 +468,40 @@ def test_unregistered_base_implementations():
assert a.ro_value_prop == 1.75
-def test_custom_caster_destruction():
- """Tests that returning a pointer to a type that gets converted with a custom type caster gets
- destroyed when the function has py::return_value_policy::take_ownership policy applied."""
+def test_ref_qualified():
+ """Tests that explicit lvalue ref-qualified methods can be called just like their
+ non ref-qualified counterparts."""
- cstats = m.destruction_tester_cstats()
- # This one *doesn't* have take_ownership: the pointer should be used but not destroyed:
- z = m.custom_caster_no_destroy()
- assert cstats.alive() == 1 and cstats.default_constructions == 1
- assert z
+ r = m.RefQualified()
+ assert r.value == 0
+ r.refQualified(17)
+ assert r.value == 17
+ assert r.constRefQualified(23) == 40
- # take_ownership applied: this constructs a new object, casts it, then destroys it:
- z = m.custom_caster_destroy()
- assert z
- assert cstats.default_constructions == 2
- # Same, but with a const pointer return (which should *not* inhibit destruction):
- z = m.custom_caster_destroy_const()
- assert z
- assert cstats.default_constructions == 3
+def test_overload_ordering():
+ "Check to see if the normal overload order (first defined) and prepend overload order works"
+ assert m.overload_order("string") == 1
+ assert m.overload_order(0) == 4
- # Make sure we still only have the original object (from ..._no_destroy()) alive:
- assert cstats.alive() == 1
+ # Different for Python 2 vs. 3
+ uni_name = type(u"").__name__
+
+ assert "1. overload_order(arg0: int) -> int" in m.overload_order.__doc__
+ assert (
+ "2. overload_order(arg0: {}) -> int".format(uni_name)
+ in m.overload_order.__doc__
+ )
+ assert (
+ "3. overload_order(arg0: {}) -> int".format(uni_name)
+ in m.overload_order.__doc__
+ )
+ assert "4. overload_order(arg0: int) -> int" in m.overload_order.__doc__
+
+ with pytest.raises(TypeError) as err:
+ m.overload_order(1.1)
+
+ assert "1. (arg0: int) -> int" in str(err.value)
+ assert "2. (arg0: {}) -> int".format(uni_name) in str(err.value)
+ assert "3. (arg0: {}) -> int".format(uni_name) in str(err.value)
+ assert "4. (arg0: int) -> int" in str(err.value)
diff --git a/3rdparty/pybind11/tests/test_modules.cpp b/3rdparty/pybind11/tests/test_modules.cpp
index c1475fa6..67387e80 100644
--- a/3rdparty/pybind11/tests/test_modules.cpp
+++ b/3rdparty/pybind11/tests/test_modules.cpp
@@ -13,6 +13,7 @@
TEST_SUBMODULE(modules, m) {
// test_nested_modules
+ // This is intentionally "py::module" to verify it still can be used in place of "py::module_"
py::module m_sub = m.def_submodule("subsubmodule");
m_sub.def("submodule_func", []() { return "submodule_func()"; });
@@ -50,6 +51,7 @@ TEST_SUBMODULE(modules, m) {
.def_readwrite("a1", &B::a1) // def_readonly uses an internal reference return policy by default
.def_readwrite("a2", &B::a2);
+ // This is intentionally "py::module" to verify it still can be used in place of "py::module_"
m.attr("OD") = py::module::import("collections").attr("OrderedDict");
// test_duplicate_registration
@@ -60,7 +62,8 @@ TEST_SUBMODULE(modules, m) {
class Dupe3 { };
class DupeException { };
- auto dm = py::module("dummy");
+ // Go ahead and leak, until we have a non-leaking py::module_ constructor
+ auto dm = py::module_::create_extension_module("dummy", nullptr, new py::module_::module_def);
auto failures = py::list();
py::class_<Dupe1>(dm, "Dupe1");
diff --git a/3rdparty/pybind11/tests/test_modules.py b/3rdparty/pybind11/tests/test_modules.py
index 2552838c..5630ccf9 100644
--- a/3rdparty/pybind11/tests/test_modules.py
+++ b/3rdparty/pybind11/tests/test_modules.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from pybind11_tests import modules as m
from pybind11_tests.modules import subsubmodule as ms
from pybind11_tests import ConstructorStats
@@ -5,9 +6,13 @@ from pybind11_tests import ConstructorStats
def test_nested_modules():
import pybind11_tests
+
assert pybind11_tests.__name__ == "pybind11_tests"
assert pybind11_tests.modules.__name__ == "pybind11_tests.modules"
- assert pybind11_tests.modules.subsubmodule.__name__ == "pybind11_tests.modules.subsubmodule"
+ assert (
+ pybind11_tests.modules.subsubmodule.__name__
+ == "pybind11_tests.modules.subsubmodule"
+ )
assert m.__name__ == "pybind11_tests.modules"
assert ms.__name__ == "pybind11_tests.modules.subsubmodule"
@@ -34,7 +39,7 @@ def test_reference_internal():
del b
assert astats.alive() == 0
assert bstats.alive() == 0
- assert astats.values() == ['1', '2', '42', '43']
+ assert astats.values() == ["1", "2", "42", "43"]
assert bstats.values() == []
assert astats.default_constructions == 0
assert bstats.default_constructions == 1
@@ -53,7 +58,7 @@ def test_importing():
from collections import OrderedDict
assert OD is OrderedDict
- assert str(OD([(1, 'a'), (2, 'b')])) == "OrderedDict([(1, 'a'), (2, 'b')])"
+ assert str(OD([(1, "a"), (2, "b")])) == "OrderedDict([(1, 'a'), (2, 'b')])"
def test_pydoc():
diff --git a/3rdparty/pybind11/tests/test_multiple_inheritance.cpp b/3rdparty/pybind11/tests/test_multiple_inheritance.cpp
index ba1674fb..e6720080 100644
--- a/3rdparty/pybind11/tests/test_multiple_inheritance.cpp
+++ b/3rdparty/pybind11/tests/test_multiple_inheritance.cpp
@@ -193,14 +193,12 @@ TEST_SUBMODULE(multiple_inheritance, m) {
.def_readwrite_static("static_value", &VanillaStaticMix2::static_value);
-#if !defined(PYPY_VERSION)
struct WithDict { };
struct VanillaDictMix1 : Vanilla, WithDict { };
struct VanillaDictMix2 : WithDict, Vanilla { };
py::class_<WithDict>(m, "WithDict", py::dynamic_attr()).def(py::init<>());
py::class_<VanillaDictMix1, Vanilla, WithDict>(m, "VanillaDictMix1").def(py::init<>());
py::class_<VanillaDictMix2, WithDict, Vanilla>(m, "VanillaDictMix2").def(py::init<>());
-#endif
// test_diamond_inheritance
// Issue #959: segfault when constructing diamond inheritance instance
diff --git a/3rdparty/pybind11/tests/test_multiple_inheritance.py b/3rdparty/pybind11/tests/test_multiple_inheritance.py
index 475dd3b3..e6a7f976 100644
--- a/3rdparty/pybind11/tests/test_multiple_inheritance.py
+++ b/3rdparty/pybind11/tests/test_multiple_inheritance.py
@@ -1,4 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
+
+import env # noqa: F401
+
from pybind11_tests import ConstructorStats
from pybind11_tests import multiple_inheritance as m
@@ -10,6 +14,8 @@ def test_multiple_inheritance_cpp():
assert mt.bar() == 4
+@pytest.mark.skipif("env.PYPY and env.PY2")
+@pytest.mark.xfail("env.PYPY and not env.PY2")
def test_multiple_inheritance_mix1():
class Base1:
def __init__(self, i):
@@ -30,7 +36,6 @@ def test_multiple_inheritance_mix1():
def test_multiple_inheritance_mix2():
-
class Base2:
def __init__(self, i):
self.i = i
@@ -49,8 +54,9 @@ def test_multiple_inheritance_mix2():
assert mt.bar() == 4
+@pytest.mark.skipif("env.PYPY and env.PY2")
+@pytest.mark.xfail("env.PYPY and not env.PY2")
def test_multiple_inheritance_python():
-
class MI1(m.Base1, m.Base2):
def __init__(self, i, j):
m.Base1.__init__(self, i)
@@ -156,7 +162,6 @@ def test_multiple_inheritance_python():
def test_multiple_inheritance_python_many_bases():
-
class MIMany14(m.BaseN1, m.BaseN2, m.BaseN3, m.BaseN4):
def __init__(self):
m.BaseN1.__init__(self, 1)
@@ -171,8 +176,16 @@ def test_multiple_inheritance_python_many_bases():
m.BaseN7.__init__(self, 7)
m.BaseN8.__init__(self, 8)
- class MIMany916(m.BaseN9, m.BaseN10, m.BaseN11, m.BaseN12, m.BaseN13, m.BaseN14, m.BaseN15,
- m.BaseN16):
+ class MIMany916(
+ m.BaseN9,
+ m.BaseN10,
+ m.BaseN11,
+ m.BaseN12,
+ m.BaseN13,
+ m.BaseN14,
+ m.BaseN15,
+ m.BaseN16,
+ ):
def __init__(self):
m.BaseN9.__init__(self, 9)
m.BaseN10.__init__(self, 10)
@@ -218,7 +231,6 @@ def test_multiple_inheritance_python_many_bases():
def test_multiple_inheritance_virtbase():
-
class MITypePy(m.Base12a):
def __init__(self, i, j):
m.Base12a.__init__(self, i, j)
@@ -231,7 +243,7 @@ def test_multiple_inheritance_virtbase():
def test_mi_static_properties():
"""Mixing bases with and without static properties should be possible
- and the result should be independent of base definition order"""
+ and the result should be independent of base definition order"""
for d in (m.VanillaStaticMix1(), m.VanillaStaticMix2()):
assert d.vanilla() == "Vanilla"
@@ -253,7 +265,7 @@ def test_mi_static_properties():
assert d.static_value == 0
-@pytest.unsupported_on_pypy
+# Requires PyPy 6+
def test_mi_dynamic_attributes():
"""Mixing bases with and without dynamic attribute support"""
diff --git a/3rdparty/pybind11/tests/test_numpy_array.cpp b/3rdparty/pybind11/tests/test_numpy_array.cpp
index 156a3bfa..a84de77f 100644
--- a/3rdparty/pybind11/tests/test_numpy_array.cpp
+++ b/3rdparty/pybind11/tests/test_numpy_array.cpp
@@ -22,7 +22,7 @@ struct DtypeCheck {
template <typename T>
DtypeCheck get_dtype_check(const char* name) {
- py::module np = py::module::import("numpy");
+ py::module_ np = py::module_::import("numpy");
DtypeCheck check{};
check.numpy = np.attr("dtype")(np.attr(name));
check.pybind11 = py::dtype::of<T>();
@@ -89,23 +89,23 @@ template<typename... Ix> arr data_t(const arr_t& a, Ix... index) {
template<typename... Ix> arr& mutate_data(arr& a, Ix... index) {
auto ptr = (uint8_t *) a.mutable_data(index...);
- for (ssize_t i = 0; i < a.nbytes() - a.offset_at(index...); i++)
+ for (py::ssize_t i = 0; i < a.nbytes() - a.offset_at(index...); i++)
ptr[i] = (uint8_t) (ptr[i] * 2);
return a;
}
template<typename... Ix> arr_t& mutate_data_t(arr_t& a, Ix... index) {
auto ptr = a.mutable_data(index...);
- for (ssize_t i = 0; i < a.size() - a.index_at(index...); i++)
+ for (py::ssize_t i = 0; i < a.size() - a.index_at(index...); i++)
ptr[i]++;
return a;
}
-template<typename... Ix> ssize_t index_at(const arr& a, Ix... idx) { return a.index_at(idx...); }
-template<typename... Ix> ssize_t index_at_t(const arr_t& a, Ix... idx) { return a.index_at(idx...); }
-template<typename... Ix> ssize_t offset_at(const arr& a, Ix... idx) { return a.offset_at(idx...); }
-template<typename... Ix> ssize_t offset_at_t(const arr_t& a, Ix... idx) { return a.offset_at(idx...); }
-template<typename... Ix> ssize_t at_t(const arr_t& a, Ix... idx) { return a.at(idx...); }
+template<typename... Ix> py::ssize_t index_at(const arr& a, Ix... idx) { return a.index_at(idx...); }
+template<typename... Ix> py::ssize_t index_at_t(const arr_t& a, Ix... idx) { return a.index_at(idx...); }
+template<typename... Ix> py::ssize_t offset_at(const arr& a, Ix... idx) { return a.offset_at(idx...); }
+template<typename... Ix> py::ssize_t offset_at_t(const arr_t& a, Ix... idx) { return a.offset_at(idx...); }
+template<typename... Ix> py::ssize_t at_t(const arr_t& a, Ix... idx) { return a.at(idx...); }
template<typename... Ix> arr_t& mutate_at_t(arr_t& a, Ix... idx) { a.mutable_at(idx...)++; return a; }
#define def_index_fn(name, type) \
@@ -133,7 +133,7 @@ template <typename T, typename T2> py::handle auxiliaries(T &&r, T2 &&r2) {
static int data_i = 42;
TEST_SUBMODULE(numpy_array, sm) {
- try { py::module::import("numpy"); }
+ try { py::module_::import("numpy"); }
catch (...) { return; }
// test_dtypes
@@ -159,9 +159,9 @@ TEST_SUBMODULE(numpy_array, sm) {
// test_array_attributes
sm.def("ndim", [](const arr& a) { return a.ndim(); });
sm.def("shape", [](const arr& a) { return arr(a.ndim(), a.shape()); });
- sm.def("shape", [](const arr& a, ssize_t dim) { return a.shape(dim); });
+ sm.def("shape", [](const arr& a, py::ssize_t dim) { return a.shape(dim); });
sm.def("strides", [](const arr& a) { return arr(a.ndim(), a.strides()); });
- sm.def("strides", [](const arr& a, ssize_t dim) { return a.strides(dim); });
+ sm.def("strides", [](const arr& a, py::ssize_t dim) { return a.strides(dim); });
sm.def("writeable", [](const arr& a) { return a.writeable(); });
sm.def("size", [](const arr& a) { return a.size(); });
sm.def("itemsize", [](const arr& a) { return a.itemsize(); });
@@ -212,7 +212,7 @@ TEST_SUBMODULE(numpy_array, sm) {
.def(py::init<>())
.def("numpy_view", [](py::object &obj) {
py::print("ArrayClass::numpy_view()");
- ArrayClass &a = obj.cast<ArrayClass&>();
+ auto &a = obj.cast<ArrayClass&>();
return py::array_t<int>({2}, {4}, a.data, obj);
}
);
@@ -281,33 +281,33 @@ TEST_SUBMODULE(numpy_array, sm) {
// test_array_unchecked_fixed_dims
sm.def("proxy_add2", [](py::array_t<double> a, double v) {
auto r = a.mutable_unchecked<2>();
- for (ssize_t i = 0; i < r.shape(0); i++)
- for (ssize_t j = 0; j < r.shape(1); j++)
+ for (py::ssize_t i = 0; i < r.shape(0); i++)
+ for (py::ssize_t j = 0; j < r.shape(1); j++)
r(i, j) += v;
}, py::arg().noconvert(), py::arg());
sm.def("proxy_init3", [](double start) {
py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
auto r = a.mutable_unchecked<3>();
- for (ssize_t i = 0; i < r.shape(0); i++)
- for (ssize_t j = 0; j < r.shape(1); j++)
- for (ssize_t k = 0; k < r.shape(2); k++)
+ for (py::ssize_t i = 0; i < r.shape(0); i++)
+ for (py::ssize_t j = 0; j < r.shape(1); j++)
+ for (py::ssize_t k = 0; k < r.shape(2); k++)
r(i, j, k) = start++;
return a;
});
sm.def("proxy_init3F", [](double start) {
py::array_t<double, py::array::f_style> a({ 3, 3, 3 });
auto r = a.mutable_unchecked<3>();
- for (ssize_t k = 0; k < r.shape(2); k++)
- for (ssize_t j = 0; j < r.shape(1); j++)
- for (ssize_t i = 0; i < r.shape(0); i++)
+ for (py::ssize_t k = 0; k < r.shape(2); k++)
+ for (py::ssize_t j = 0; j < r.shape(1); j++)
+ for (py::ssize_t i = 0; i < r.shape(0); i++)
r(i, j, k) = start++;
return a;
});
sm.def("proxy_squared_L2_norm", [](py::array_t<double> a) {
auto r = a.unchecked<1>();
double sumsq = 0;
- for (ssize_t i = 0; i < r.shape(0); i++)
+ for (py::ssize_t i = 0; i < r.shape(0); i++)
sumsq += r[i] * r(i); // Either notation works for a 1D array
return sumsq;
});
@@ -318,22 +318,34 @@ TEST_SUBMODULE(numpy_array, sm) {
return auxiliaries(r, r2);
});
+ sm.def("proxy_auxiliaries1_const_ref", [](py::array_t<double> a) {
+ const auto &r = a.unchecked<1>();
+ const auto &r2 = a.mutable_unchecked<1>();
+ return r(0) == r2(0) && r[0] == r2[0];
+ });
+
+ sm.def("proxy_auxiliaries2_const_ref", [](py::array_t<double> a) {
+ const auto &r = a.unchecked<2>();
+ const auto &r2 = a.mutable_unchecked<2>();
+ return r(0, 0) == r2(0, 0);
+ });
+
// test_array_unchecked_dyn_dims
// Same as the above, but without a compile-time dimensions specification:
sm.def("proxy_add2_dyn", [](py::array_t<double> a, double v) {
auto r = a.mutable_unchecked();
if (r.ndim() != 2) throw std::domain_error("error: ndim != 2");
- for (ssize_t i = 0; i < r.shape(0); i++)
- for (ssize_t j = 0; j < r.shape(1); j++)
+ for (py::ssize_t i = 0; i < r.shape(0); i++)
+ for (py::ssize_t j = 0; j < r.shape(1); j++)
r(i, j) += v;
}, py::arg().noconvert(), py::arg());
sm.def("proxy_init3_dyn", [](double start) {
py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
auto r = a.mutable_unchecked();
if (r.ndim() != 3) throw std::domain_error("error: ndim != 3");
- for (ssize_t i = 0; i < r.shape(0); i++)
- for (ssize_t j = 0; j < r.shape(1); j++)
- for (ssize_t k = 0; k < r.shape(2); k++)
+ for (py::ssize_t i = 0; i < r.shape(0); i++)
+ for (py::ssize_t j = 0; j < r.shape(1); j++)
+ for (py::ssize_t k = 0; k < r.shape(2); k++)
r(i, j, k) = start++;
return a;
});
@@ -362,7 +374,7 @@ TEST_SUBMODULE(numpy_array, sm) {
// test_array_resize
// reshape array to 2D without changing size
sm.def("array_reshape2", [](py::array_t<double> a) {
- const ssize_t dim_sz = (ssize_t)std::sqrt(a.size());
+ const auto dim_sz = (py::ssize_t)std::sqrt(a.size());
if (dim_sz * dim_sz != a.size())
throw std::domain_error("array_reshape2: input array total size is not a squared integer");
a.resize({dim_sz, dim_sz});
@@ -382,9 +394,45 @@ TEST_SUBMODULE(numpy_array, sm) {
return a;
});
-#if PY_MAJOR_VERSION >= 3
- sm.def("index_using_ellipsis", [](py::array a) {
- return a[py::make_tuple(0, py::ellipsis(), 0)];
- });
-#endif
+ sm.def("index_using_ellipsis", [](py::array a) {
+ return a[py::make_tuple(0, py::ellipsis(), 0)];
+ });
+
+ // test_argument_conversions
+ sm.def("accept_double",
+ [](py::array_t<double, 0>) {},
+ py::arg("a"));
+ sm.def("accept_double_forcecast",
+ [](py::array_t<double, py::array::forcecast>) {},
+ py::arg("a"));
+ sm.def("accept_double_c_style",
+ [](py::array_t<double, py::array::c_style>) {},
+ py::arg("a"));
+ sm.def("accept_double_c_style_forcecast",
+ [](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
+ py::arg("a"));
+ sm.def("accept_double_f_style",
+ [](py::array_t<double, py::array::f_style>) {},
+ py::arg("a"));
+ sm.def("accept_double_f_style_forcecast",
+ [](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
+ py::arg("a"));
+ sm.def("accept_double_noconvert",
+ [](py::array_t<double, 0>) {},
+ py::arg("a").noconvert());
+ sm.def("accept_double_forcecast_noconvert",
+ [](py::array_t<double, py::array::forcecast>) {},
+ py::arg("a").noconvert());
+ sm.def("accept_double_c_style_noconvert",
+ [](py::array_t<double, py::array::c_style>) {},
+ py::arg("a").noconvert());
+ sm.def("accept_double_c_style_forcecast_noconvert",
+ [](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
+ py::arg("a").noconvert());
+ sm.def("accept_double_f_style_noconvert",
+ [](py::array_t<double, py::array::f_style>) {},
+ py::arg("a").noconvert());
+ sm.def("accept_double_f_style_forcecast_noconvert",
+ [](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
+ py::arg("a").noconvert());
}
diff --git a/3rdparty/pybind11/tests/test_numpy_array.py b/3rdparty/pybind11/tests/test_numpy_array.py
index d0a6324d..02f3ecfc 100644
--- a/3rdparty/pybind11/tests/test_numpy_array.py
+++ b/3rdparty/pybind11/tests/test_numpy_array.py
@@ -1,10 +1,11 @@
+# -*- coding: utf-8 -*-
import pytest
-from pybind11_tests import numpy_array as m
-pytestmark = pytest.requires_numpy
+import env # noqa: F401
+
+from pybind11_tests import numpy_array as m
-with pytest.suppress(ImportError):
- import numpy as np
+np = pytest.importorskip("numpy")
def test_dtypes():
@@ -18,33 +19,36 @@ def test_dtypes():
print(check)
assert check.numpy == check.pybind11, check
if check.numpy.num != check.pybind11.num:
- print("NOTE: typenum mismatch for {}: {} != {}".format(
- check, check.numpy.num, check.pybind11.num))
+ print(
+ "NOTE: typenum mismatch for {}: {} != {}".format(
+ check, check.numpy.num, check.pybind11.num
+ )
+ )
-@pytest.fixture(scope='function')
+@pytest.fixture(scope="function")
def arr():
- return np.array([[1, 2, 3], [4, 5, 6]], '=u2')
+ return np.array([[1, 2, 3], [4, 5, 6]], "=u2")
def test_array_attributes():
- a = np.array(0, 'f8')
+ a = np.array(0, "f8")
assert m.ndim(a) == 0
assert all(m.shape(a) == [])
assert all(m.strides(a) == [])
with pytest.raises(IndexError) as excinfo:
m.shape(a, 0)
- assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)'
+ assert str(excinfo.value) == "invalid axis: 0 (ndim = 0)"
with pytest.raises(IndexError) as excinfo:
m.strides(a, 0)
- assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)'
+ assert str(excinfo.value) == "invalid axis: 0 (ndim = 0)"
assert m.writeable(a)
assert m.size(a) == 1
assert m.itemsize(a) == 8
assert m.nbytes(a) == 8
assert m.owndata(a)
- a = np.array([[1, 2, 3], [4, 5, 6]], 'u2').view()
+ a = np.array([[1, 2, 3], [4, 5, 6]], "u2").view()
a.flags.writeable = False
assert m.ndim(a) == 2
assert all(m.shape(a) == [2, 3])
@@ -55,10 +59,10 @@ def test_array_attributes():
assert m.strides(a, 1) == 2
with pytest.raises(IndexError) as excinfo:
m.shape(a, 2)
- assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)'
+ assert str(excinfo.value) == "invalid axis: 2 (ndim = 2)"
with pytest.raises(IndexError) as excinfo:
m.strides(a, 2)
- assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)'
+ assert str(excinfo.value) == "invalid axis: 2 (ndim = 2)"
assert not m.writeable(a)
assert m.size(a) == 6
assert m.itemsize(a) == 2
@@ -66,7 +70,9 @@ def test_array_attributes():
assert not m.owndata(a)
-@pytest.mark.parametrize('args, ret', [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)])
+@pytest.mark.parametrize(
+ "args, ret", [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)]
+)
def test_index_offset(arr, args, ret):
assert m.index_at(arr, *args) == ret
assert m.index_at_t(arr, *args) == ret
@@ -75,31 +81,46 @@ def test_index_offset(arr, args, ret):
def test_dim_check_fail(arr):
- for func in (m.index_at, m.index_at_t, m.offset_at, m.offset_at_t, m.data, m.data_t,
- m.mutate_data, m.mutate_data_t):
+ for func in (
+ m.index_at,
+ m.index_at_t,
+ m.offset_at,
+ m.offset_at_t,
+ m.data,
+ m.data_t,
+ m.mutate_data,
+ m.mutate_data_t,
+ ):
with pytest.raises(IndexError) as excinfo:
func(arr, 1, 2, 3)
- assert str(excinfo.value) == 'too many indices for an array: 3 (ndim = 2)'
-
-
-@pytest.mark.parametrize('args, ret',
- [([], [1, 2, 3, 4, 5, 6]),
- ([1], [4, 5, 6]),
- ([0, 1], [2, 3, 4, 5, 6]),
- ([1, 2], [6])])
+ assert str(excinfo.value) == "too many indices for an array: 3 (ndim = 2)"
+
+
+@pytest.mark.parametrize(
+ "args, ret",
+ [
+ ([], [1, 2, 3, 4, 5, 6]),
+ ([1], [4, 5, 6]),
+ ([0, 1], [2, 3, 4, 5, 6]),
+ ([1, 2], [6]),
+ ],
+)
def test_data(arr, args, ret):
from sys import byteorder
+
assert all(m.data_t(arr, *args) == ret)
- assert all(m.data(arr, *args)[(0 if byteorder == 'little' else 1)::2] == ret)
- assert all(m.data(arr, *args)[(1 if byteorder == 'little' else 0)::2] == 0)
+ assert all(m.data(arr, *args)[(0 if byteorder == "little" else 1) :: 2] == ret)
+ assert all(m.data(arr, *args)[(1 if byteorder == "little" else 0) :: 2] == 0)
-@pytest.mark.parametrize('dim', [0, 1, 3])
+@pytest.mark.parametrize("dim", [0, 1, 3])
def test_at_fail(arr, dim):
for func in m.at_t, m.mutate_at_t:
with pytest.raises(IndexError) as excinfo:
func(arr, *([0] * dim))
- assert str(excinfo.value) == 'index dimension mismatch: {} (ndim = 2)'.format(dim)
+ assert str(excinfo.value) == "index dimension mismatch: {} (ndim = 2)".format(
+ dim
+ )
def test_at(arr):
@@ -112,10 +133,14 @@ def test_at(arr):
def test_mutate_readonly(arr):
arr.flags.writeable = False
- for func, args in (m.mutate_data, ()), (m.mutate_data_t, ()), (m.mutate_at_t, (0, 0)):
+ for func, args in (
+ (m.mutate_data, ()),
+ (m.mutate_data_t, ()),
+ (m.mutate_at_t, (0, 0)),
+ ):
with pytest.raises(ValueError) as excinfo:
func(arr, *args)
- assert str(excinfo.value) == 'array is not writeable'
+ assert str(excinfo.value) == "array is not writeable"
def test_mutate_data(arr):
@@ -133,14 +158,22 @@ def test_mutate_data(arr):
def test_bounds_check(arr):
- for func in (m.index_at, m.index_at_t, m.data, m.data_t,
- m.mutate_data, m.mutate_data_t, m.at_t, m.mutate_at_t):
+ for func in (
+ m.index_at,
+ m.index_at_t,
+ m.data,
+ m.data_t,
+ m.mutate_data,
+ m.mutate_data_t,
+ m.at_t,
+ m.mutate_at_t,
+ ):
with pytest.raises(IndexError) as excinfo:
func(arr, 2, 0)
- assert str(excinfo.value) == 'index 2 is out of bounds for axis 0 with size 2'
+ assert str(excinfo.value) == "index 2 is out of bounds for axis 0 with size 2"
with pytest.raises(IndexError) as excinfo:
func(arr, 0, 4)
- assert str(excinfo.value) == 'index 4 is out of bounds for axis 1 with size 3'
+ assert str(excinfo.value) == "index 4 is out of bounds for axis 1 with size 3"
def test_make_c_f_array():
@@ -162,10 +195,11 @@ def test_make_empty_shaped_array():
def test_wrap():
def assert_references(a, b, base=None):
from distutils.version import LooseVersion
+
if base is None:
base = a
assert a is not b
- assert a.__array_interface__['data'][0] == b.__array_interface__['data'][0]
+ assert a.__array_interface__["data"][0] == b.__array_interface__["data"][0]
assert a.shape == b.shape
assert a.strides == b.strides
assert a.flags.c_contiguous == b.flags.c_contiguous
@@ -188,12 +222,12 @@ def test_wrap():
a2 = m.wrap(a1)
assert_references(a1, a2)
- a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='F')
+ a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="F")
assert a1.flags.owndata and a1.base is None
a2 = m.wrap(a1)
assert_references(a1, a2)
- a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='C')
+ a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="C")
a1.flags.writeable = False
a2 = m.wrap(a1)
assert_references(a1, a2)
@@ -223,11 +257,14 @@ def test_numpy_view(capture):
assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32))
del ac
pytest.gc_collect()
- assert capture == """
+ assert (
+ capture
+ == """
ArrayClass()
ArrayClass::numpy_view()
ArrayClass::numpy_view()
"""
+ )
ac_view_1[0] = 4
ac_view_1[1] = 3
assert ac_view_2[0] == 4
@@ -237,12 +274,14 @@ def test_numpy_view(capture):
del ac_view_2
pytest.gc_collect()
pytest.gc_collect()
- assert capture == """
+ assert (
+ capture
+ == """
~ArrayClass()
"""
+ )
-@pytest.unsupported_on_pypy
def test_cast_numpy_int64_to_uint64():
m.function_taking_uint64(123)
m.function_taking_uint64(np.uint64(123))
@@ -271,89 +310,94 @@ def test_constructors():
def test_overload_resolution(msg):
# Exact overload matches:
- assert m.overloaded(np.array([1], dtype='float64')) == 'double'
- assert m.overloaded(np.array([1], dtype='float32')) == 'float'
- assert m.overloaded(np.array([1], dtype='ushort')) == 'unsigned short'
- assert m.overloaded(np.array([1], dtype='intc')) == 'int'
- assert m.overloaded(np.array([1], dtype='longlong')) == 'long long'
- assert m.overloaded(np.array([1], dtype='complex')) == 'double complex'
- assert m.overloaded(np.array([1], dtype='csingle')) == 'float complex'
+ assert m.overloaded(np.array([1], dtype="float64")) == "double"
+ assert m.overloaded(np.array([1], dtype="float32")) == "float"
+ assert m.overloaded(np.array([1], dtype="ushort")) == "unsigned short"
+ assert m.overloaded(np.array([1], dtype="intc")) == "int"
+ assert m.overloaded(np.array([1], dtype="longlong")) == "long long"
+ assert m.overloaded(np.array([1], dtype="complex")) == "double complex"
+ assert m.overloaded(np.array([1], dtype="csingle")) == "float complex"
# No exact match, should call first convertible version:
- assert m.overloaded(np.array([1], dtype='uint8')) == 'double'
+ assert m.overloaded(np.array([1], dtype="uint8")) == "double"
with pytest.raises(TypeError) as excinfo:
m.overloaded("not an array")
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
overloaded(): incompatible function arguments. The following argument types are supported:
- 1. (arg0: numpy.ndarray[float64]) -> str
- 2. (arg0: numpy.ndarray[float32]) -> str
- 3. (arg0: numpy.ndarray[int32]) -> str
- 4. (arg0: numpy.ndarray[uint16]) -> str
- 5. (arg0: numpy.ndarray[int64]) -> str
- 6. (arg0: numpy.ndarray[complex128]) -> str
- 7. (arg0: numpy.ndarray[complex64]) -> str
+ 1. (arg0: numpy.ndarray[numpy.float64]) -> str
+ 2. (arg0: numpy.ndarray[numpy.float32]) -> str
+ 3. (arg0: numpy.ndarray[numpy.int32]) -> str
+ 4. (arg0: numpy.ndarray[numpy.uint16]) -> str
+ 5. (arg0: numpy.ndarray[numpy.int64]) -> str
+ 6. (arg0: numpy.ndarray[numpy.complex128]) -> str
+ 7. (arg0: numpy.ndarray[numpy.complex64]) -> str
Invoked with: 'not an array'
"""
+ )
- assert m.overloaded2(np.array([1], dtype='float64')) == 'double'
- assert m.overloaded2(np.array([1], dtype='float32')) == 'float'
- assert m.overloaded2(np.array([1], dtype='complex64')) == 'float complex'
- assert m.overloaded2(np.array([1], dtype='complex128')) == 'double complex'
- assert m.overloaded2(np.array([1], dtype='float32')) == 'float'
+ assert m.overloaded2(np.array([1], dtype="float64")) == "double"
+ assert m.overloaded2(np.array([1], dtype="float32")) == "float"
+ assert m.overloaded2(np.array([1], dtype="complex64")) == "float complex"
+ assert m.overloaded2(np.array([1], dtype="complex128")) == "double complex"
+ assert m.overloaded2(np.array([1], dtype="float32")) == "float"
- assert m.overloaded3(np.array([1], dtype='float64')) == 'double'
- assert m.overloaded3(np.array([1], dtype='intc')) == 'int'
+ assert m.overloaded3(np.array([1], dtype="float64")) == "double"
+ assert m.overloaded3(np.array([1], dtype="intc")) == "int"
expected_exc = """
overloaded3(): incompatible function arguments. The following argument types are supported:
- 1. (arg0: numpy.ndarray[int32]) -> str
- 2. (arg0: numpy.ndarray[float64]) -> str
+ 1. (arg0: numpy.ndarray[numpy.int32]) -> str
+ 2. (arg0: numpy.ndarray[numpy.float64]) -> str
Invoked with: """
with pytest.raises(TypeError) as excinfo:
- m.overloaded3(np.array([1], dtype='uintc'))
- assert msg(excinfo.value) == expected_exc + repr(np.array([1], dtype='uint32'))
+ m.overloaded3(np.array([1], dtype="uintc"))
+ assert msg(excinfo.value) == expected_exc + repr(np.array([1], dtype="uint32"))
with pytest.raises(TypeError) as excinfo:
- m.overloaded3(np.array([1], dtype='float32'))
- assert msg(excinfo.value) == expected_exc + repr(np.array([1.], dtype='float32'))
+ m.overloaded3(np.array([1], dtype="float32"))
+ assert msg(excinfo.value) == expected_exc + repr(np.array([1.0], dtype="float32"))
with pytest.raises(TypeError) as excinfo:
- m.overloaded3(np.array([1], dtype='complex'))
- assert msg(excinfo.value) == expected_exc + repr(np.array([1. + 0.j]))
+ m.overloaded3(np.array([1], dtype="complex"))
+ assert msg(excinfo.value) == expected_exc + repr(np.array([1.0 + 0.0j]))
# Exact matches:
- assert m.overloaded4(np.array([1], dtype='double')) == 'double'
- assert m.overloaded4(np.array([1], dtype='longlong')) == 'long long'
+ assert m.overloaded4(np.array([1], dtype="double")) == "double"
+ assert m.overloaded4(np.array([1], dtype="longlong")) == "long long"
# Non-exact matches requiring conversion. Since float to integer isn't a
# save conversion, it should go to the double overload, but short can go to
# either (and so should end up on the first-registered, the long long).
- assert m.overloaded4(np.array([1], dtype='float32')) == 'double'
- assert m.overloaded4(np.array([1], dtype='short')) == 'long long'
+ assert m.overloaded4(np.array([1], dtype="float32")) == "double"
+ assert m.overloaded4(np.array([1], dtype="short")) == "long long"
- assert m.overloaded5(np.array([1], dtype='double')) == 'double'
- assert m.overloaded5(np.array([1], dtype='uintc')) == 'unsigned int'
- assert m.overloaded5(np.array([1], dtype='float32')) == 'unsigned int'
+ assert m.overloaded5(np.array([1], dtype="double")) == "double"
+ assert m.overloaded5(np.array([1], dtype="uintc")) == "unsigned int"
+ assert m.overloaded5(np.array([1], dtype="float32")) == "unsigned int"
def test_greedy_string_overload():
"""Tests fix for #685 - ndarray shouldn't go to std::string overload"""
assert m.issue685("abc") == "string"
- assert m.issue685(np.array([97, 98, 99], dtype='b')) == "array"
+ assert m.issue685(np.array([97, 98, 99], dtype="b")) == "array"
assert m.issue685(123) == "other"
def test_array_unchecked_fixed_dims(msg):
- z1 = np.array([[1, 2], [3, 4]], dtype='float64')
+ z1 = np.array([[1, 2], [3, 4]], dtype="float64")
m.proxy_add2(z1, 10)
assert np.all(z1 == [[11, 12], [13, 14]])
with pytest.raises(ValueError) as excinfo:
- m.proxy_add2(np.array([1., 2, 3]), 5.0)
- assert msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2"
+ m.proxy_add2(np.array([1.0, 2, 3]), 5.0)
+ assert (
+ msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2"
+ )
- expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int')
+ expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype="int")
assert np.all(m.proxy_init3(3.0) == expect_c)
expect_f = np.transpose(expect_c)
assert np.all(m.proxy_init3F(3.0) == expect_f)
@@ -364,13 +408,16 @@ def test_array_unchecked_fixed_dims(msg):
assert m.proxy_auxiliaries2(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
assert m.proxy_auxiliaries2(z1) == m.array_auxiliaries2(z1)
+ assert m.proxy_auxiliaries1_const_ref(z1[0, :])
+ assert m.proxy_auxiliaries2_const_ref(z1)
+
def test_array_unchecked_dyn_dims(msg):
- z1 = np.array([[1, 2], [3, 4]], dtype='float64')
+ z1 = np.array([[1, 2], [3, 4]], dtype="float64")
m.proxy_add2_dyn(z1, 10)
assert np.all(z1 == [[11, 12], [13, 14]])
- expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int')
+ expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype="int")
assert np.all(m.proxy_init3_dyn(3.0) == expect_c)
assert m.proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
@@ -380,15 +427,15 @@ def test_array_unchecked_dyn_dims(msg):
def test_array_failure():
with pytest.raises(ValueError) as excinfo:
m.array_fail_test()
- assert str(excinfo.value) == 'cannot create a pybind11::array from a nullptr'
+ assert str(excinfo.value) == "cannot create a pybind11::array from a nullptr"
with pytest.raises(ValueError) as excinfo:
m.array_t_fail_test()
- assert str(excinfo.value) == 'cannot create a pybind11::array_t from a nullptr'
+ assert str(excinfo.value) == "cannot create a pybind11::array_t from a nullptr"
with pytest.raises(ValueError) as excinfo:
m.array_fail_test_negative_size()
- assert str(excinfo.value) == 'negative dimensions are not allowed'
+ assert str(excinfo.value) == "negative dimensions are not allowed"
def test_initializer_list():
@@ -399,46 +446,93 @@ def test_initializer_list():
def test_array_resize(msg):
- a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='float64')
+ a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype="float64")
m.array_reshape2(a)
- assert(a.size == 9)
- assert(np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]))
+ assert a.size == 9
+ assert np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]])
# total size change should succced with refcheck off
m.array_resize3(a, 4, False)
- assert(a.size == 64)
+ assert a.size == 64
# ... and fail with refcheck on
try:
m.array_resize3(a, 3, True)
except ValueError as e:
- assert(str(e).startswith("cannot resize an array"))
+ assert str(e).startswith("cannot resize an array")
# transposed array doesn't own data
b = a.transpose()
try:
m.array_resize3(b, 3, False)
except ValueError as e:
- assert(str(e).startswith("cannot resize this array: it does not own its data"))
+ assert str(e).startswith("cannot resize this array: it does not own its data")
# ... but reshape should be fine
m.array_reshape2(b)
- assert(b.shape == (8, 8))
+ assert b.shape == (8, 8)
-@pytest.unsupported_on_pypy
+@pytest.mark.xfail("env.PYPY")
def test_array_create_and_resize(msg):
a = m.create_and_resize(2)
- assert(a.size == 4)
- assert(np.all(a == 42.))
+ assert a.size == 4
+ assert np.all(a == 42.0)
-@pytest.unsupported_on_py2
def test_index_using_ellipsis():
a = m.index_using_ellipsis(np.zeros((5, 6, 7)))
assert a.shape == (6,)
-@pytest.unsupported_on_pypy
+@pytest.mark.parametrize("forcecast", [False, True])
+@pytest.mark.parametrize("contiguity", [None, "C", "F"])
+@pytest.mark.parametrize("noconvert", [False, True])
+@pytest.mark.filterwarnings(
+ "ignore:Casting complex values to real discards the imaginary part:numpy.ComplexWarning"
+)
+def test_argument_conversions(forcecast, contiguity, noconvert):
+ function_name = "accept_double"
+ if contiguity == "C":
+ function_name += "_c_style"
+ elif contiguity == "F":
+ function_name += "_f_style"
+ if forcecast:
+ function_name += "_forcecast"
+ if noconvert:
+ function_name += "_noconvert"
+ function = getattr(m, function_name)
+
+ for dtype in [np.dtype("float32"), np.dtype("float64"), np.dtype("complex128")]:
+ for order in ["C", "F"]:
+ for shape in [(2, 2), (1, 3, 1, 1), (1, 1, 1), (0,)]:
+ if not noconvert:
+ # If noconvert is not passed, only complex128 needs to be truncated and
+ # "cannot be safely obtained". So without `forcecast`, the argument shouldn't
+ # be accepted.
+ should_raise = dtype.name == "complex128" and not forcecast
+ else:
+ # If noconvert is passed, only float64 and the matching order is accepted.
+ # If at most one dimension has a size greater than 1, the array is also
+ # trivially contiguous.
+ trivially_contiguous = sum(1 for d in shape if d > 1) <= 1
+ should_raise = dtype.name != "float64" or (
+ contiguity is not None
+ and contiguity != order
+ and not trivially_contiguous
+ )
+
+ array = np.zeros(shape, dtype=dtype, order=order)
+ if not should_raise:
+ function(array)
+ else:
+ with pytest.raises(
+ TypeError, match="incompatible function arguments"
+ ):
+ function(array)
+
+
+@pytest.mark.xfail("env.PYPY")
def test_dtype_refcount_leak():
from sys import getrefcount
+
dtype = np.dtype(np.float_)
a = np.array([1], dtype=dtype)
before = getrefcount(dtype)
diff --git a/3rdparty/pybind11/tests/test_numpy_dtypes.cpp b/3rdparty/pybind11/tests/test_numpy_dtypes.cpp
index 467e0253..b2e5e607 100644
--- a/3rdparty/pybind11/tests/test_numpy_dtypes.cpp
+++ b/3rdparty/pybind11/tests/test_numpy_dtypes.cpp
@@ -168,7 +168,7 @@ py::list print_recarray(py::array_t<S, 0> arr) {
const auto req = arr.request();
const auto ptr = static_cast<S*>(req.ptr);
auto l = py::list();
- for (ssize_t i = 0; i < req.size; i++) {
+ for (py::ssize_t i = 0; i < req.size; i++) {
std::stringstream ss;
ss << ptr[i];
l.append(py::str(ss.str()));
@@ -180,8 +180,8 @@ py::array_t<int32_t, 0> test_array_ctors(int i) {
using arr_t = py::array_t<int32_t, 0>;
std::vector<int32_t> data { 1, 2, 3, 4, 5, 6 };
- std::vector<ssize_t> shape { 3, 2 };
- std::vector<ssize_t> strides { 8, 4 };
+ std::vector<py::ssize_t> shape { 3, 2 };
+ std::vector<py::ssize_t> strides { 8, 4 };
auto ptr = data.data();
auto vptr = (void *) ptr;
@@ -255,11 +255,30 @@ struct A {};
struct B {};
TEST_SUBMODULE(numpy_dtypes, m) {
- try { py::module::import("numpy"); }
+ try { py::module_::import("numpy"); }
catch (...) { return; }
// typeinfo may be registered before the dtype descriptor for scalar casts to work...
- py::class_<SimpleStruct>(m, "SimpleStruct");
+ py::class_<SimpleStruct>(m, "SimpleStruct")
+ // Explicit construct to ensure zero-valued initialization.
+ .def(py::init([]() { return SimpleStruct(); }))
+ .def_readwrite("bool_", &SimpleStruct::bool_)
+ .def_readwrite("uint_", &SimpleStruct::uint_)
+ .def_readwrite("float_", &SimpleStruct::float_)
+ .def_readwrite("ldbl_", &SimpleStruct::ldbl_)
+ .def("astuple", [](const SimpleStruct& self) {
+ return py::make_tuple(self.bool_, self.uint_, self.float_, self.ldbl_);
+ })
+ .def_static("fromtuple", [](const py::tuple tup) {
+ if (py::len(tup) != 4) {
+ throw py::cast_error("Invalid size");
+ }
+ return SimpleStruct{
+ tup[0].cast<bool>(),
+ tup[1].cast<uint32_t>(),
+ tup[2].cast<float>(),
+ tup[3].cast<long double>()};
+ });
PYBIND11_NUMPY_DTYPE(SimpleStruct, bool_, uint_, float_, ldbl_);
PYBIND11_NUMPY_DTYPE(SimpleStructReordered, bool_, uint_, float_, ldbl_);
@@ -379,7 +398,7 @@ TEST_SUBMODULE(numpy_dtypes, m) {
if (non_empty) {
auto req = arr.request();
auto ptr = static_cast<StringStruct*>(req.ptr);
- for (ssize_t i = 0; i < req.size * req.itemsize; i++)
+ for (py::ssize_t i = 0; i < req.size * req.itemsize; i++)
static_cast<char*>(req.ptr)[i] = 0;
ptr[1].a[0] = 'a'; ptr[1].b[0] = 'a';
ptr[2].a[0] = 'a'; ptr[2].b[0] = 'a';
@@ -462,10 +481,16 @@ TEST_SUBMODULE(numpy_dtypes, m) {
m.def("buffer_to_dtype", [](py::buffer& buf) { return py::dtype(buf.request()); });
// test_scalar_conversion
- m.def("f_simple", [](SimpleStruct s) { return s.uint_ * 10; });
+ auto f_simple = [](SimpleStruct s) { return s.uint_ * 10; };
+ m.def("f_simple", f_simple);
m.def("f_packed", [](PackedStruct s) { return s.uint_ * 10; });
m.def("f_nested", [](NestedStruct s) { return s.a.uint_ * 10; });
+ // test_vectorize
+ m.def("f_simple_vectorized", py::vectorize(f_simple));
+ auto f_simple_pass_thru = [](SimpleStruct s) { return s; };
+ m.def("f_simple_pass_thru_vectorized", py::vectorize(f_simple_pass_thru));
+
// test_register_dtype
m.def("register_dtype", []() { PYBIND11_NUMPY_DTYPE(SimpleStruct, bool_, uint_, float_, ldbl_); });
diff --git a/3rdparty/pybind11/tests/test_numpy_dtypes.py b/3rdparty/pybind11/tests/test_numpy_dtypes.py
index 2e638851..f56b776a 100644
--- a/3rdparty/pybind11/tests/test_numpy_dtypes.py
+++ b/3rdparty/pybind11/tests/test_numpy_dtypes.py
@@ -1,64 +1,80 @@
+# -*- coding: utf-8 -*-
import re
+
import pytest
-from pybind11_tests import numpy_dtypes as m
-pytestmark = pytest.requires_numpy
+import env # noqa: F401
-with pytest.suppress(ImportError):
- import numpy as np
+from pybind11_tests import numpy_dtypes as m
+np = pytest.importorskip("numpy")
-@pytest.fixture(scope='module')
+
+@pytest.fixture(scope="module")
def simple_dtype():
- ld = np.dtype('longdouble')
- return np.dtype({'names': ['bool_', 'uint_', 'float_', 'ldbl_'],
- 'formats': ['?', 'u4', 'f4', 'f{}'.format(ld.itemsize)],
- 'offsets': [0, 4, 8, (16 if ld.alignment > 4 else 12)]})
+ ld = np.dtype("longdouble")
+ return np.dtype(
+ {
+ "names": ["bool_", "uint_", "float_", "ldbl_"],
+ "formats": ["?", "u4", "f4", "f{}".format(ld.itemsize)],
+ "offsets": [0, 4, 8, (16 if ld.alignment > 4 else 12)],
+ }
+ )
-@pytest.fixture(scope='module')
+@pytest.fixture(scope="module")
def packed_dtype():
- return np.dtype([('bool_', '?'), ('uint_', 'u4'), ('float_', 'f4'), ('ldbl_', 'g')])
+ return np.dtype([("bool_", "?"), ("uint_", "u4"), ("float_", "f4"), ("ldbl_", "g")])
def dt_fmt():
from sys import byteorder
- e = '<' if byteorder == 'little' else '>'
- return ("{{'names':['bool_','uint_','float_','ldbl_'],"
- " 'formats':['?','" + e + "u4','" + e + "f4','" + e + "f{}'],"
- " 'offsets':[0,4,8,{}], 'itemsize':{}}}")
+
+ e = "<" if byteorder == "little" else ">"
+ return (
+ "{{'names':['bool_','uint_','float_','ldbl_'],"
+ " 'formats':['?','" + e + "u4','" + e + "f4','" + e + "f{}'],"
+ " 'offsets':[0,4,8,{}], 'itemsize':{}}}"
+ )
def simple_dtype_fmt():
- ld = np.dtype('longdouble')
+ ld = np.dtype("longdouble")
simple_ld_off = 12 + 4 * (ld.alignment > 4)
return dt_fmt().format(ld.itemsize, simple_ld_off, simple_ld_off + ld.itemsize)
def packed_dtype_fmt():
from sys import byteorder
+
return "[('bool_', '?'), ('uint_', '{e}u4'), ('float_', '{e}f4'), ('ldbl_', '{e}f{}')]".format(
- np.dtype('longdouble').itemsize, e='<' if byteorder == 'little' else '>')
+ np.dtype("longdouble").itemsize, e="<" if byteorder == "little" else ">"
+ )
def partial_ld_offset():
- return 12 + 4 * (np.dtype('uint64').alignment > 4) + 8 + 8 * (
- np.dtype('longdouble').alignment > 8)
+ return (
+ 12
+ + 4 * (np.dtype("uint64").alignment > 4)
+ + 8
+ + 8 * (np.dtype("longdouble").alignment > 8)
+ )
def partial_dtype_fmt():
- ld = np.dtype('longdouble')
+ ld = np.dtype("longdouble")
partial_ld_off = partial_ld_offset()
return dt_fmt().format(ld.itemsize, partial_ld_off, partial_ld_off + ld.itemsize)
def partial_nested_fmt():
- ld = np.dtype('longdouble')
+ ld = np.dtype("longdouble")
partial_nested_off = 8 + 8 * (ld.alignment > 8)
partial_ld_off = partial_ld_offset()
partial_nested_size = partial_nested_off * 2 + partial_ld_off + ld.itemsize
return "{{'names':['a'], 'formats':[{}], 'offsets':[{}], 'itemsize':{}}}".format(
- partial_dtype_fmt(), partial_nested_off, partial_nested_size)
+ partial_dtype_fmt(), partial_nested_off, partial_nested_size
+ )
def assert_equal(actual, expected_data, expected_dtype):
@@ -68,15 +84,19 @@ def assert_equal(actual, expected_data, expected_dtype):
def test_format_descriptors():
with pytest.raises(RuntimeError) as excinfo:
m.get_format_unbound()
- assert re.match('^NumPy type info missing for .*UnboundStruct.*$', str(excinfo.value))
+ assert re.match(
+ "^NumPy type info missing for .*UnboundStruct.*$", str(excinfo.value)
+ )
- ld = np.dtype('longdouble')
- ldbl_fmt = ('4x' if ld.alignment > 4 else '') + ld.char
+ ld = np.dtype("longdouble")
+ ldbl_fmt = ("4x" if ld.alignment > 4 else "") + ld.char
ss_fmt = "^T{?:bool_:3xI:uint_:f:float_:" + ldbl_fmt + ":ldbl_:}"
- dbl = np.dtype('double')
- partial_fmt = ("^T{?:bool_:3xI:uint_:f:float_:" +
- str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8)) +
- "xg:ldbl_:}")
+ dbl = np.dtype("double")
+ partial_fmt = (
+ "^T{?:bool_:3xI:uint_:f:float_:"
+ + str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8))
+ + "xg:ldbl_:}"
+ )
nested_extra = str(max(8, ld.alignment))
assert m.print_format_descriptors() == [
ss_fmt,
@@ -86,14 +106,15 @@ def test_format_descriptors():
"^T{" + nested_extra + "x" + partial_fmt + ":a:" + nested_extra + "x}",
"^T{3s:a:3s:b:}",
"^T{(3)4s:a:(2)i:b:(3)B:c:1x(4, 2)f:d:}",
- '^T{q:e1:B:e2:}',
- '^T{Zf:cflt:Zd:cdbl:}'
+ "^T{q:e1:B:e2:}",
+ "^T{Zf:cflt:Zd:cdbl:}",
]
def test_dtype(simple_dtype):
from sys import byteorder
- e = '<' if byteorder == 'little' else '>'
+
+ e = "<" if byteorder == "little" else ">"
assert m.print_dtypes() == [
simple_dtype_fmt(),
@@ -102,30 +123,60 @@ def test_dtype(simple_dtype):
partial_dtype_fmt(),
partial_nested_fmt(),
"[('a', 'S3'), ('b', 'S3')]",
- ("{{'names':['a','b','c','d'], " +
- "'formats':[('S4', (3,)),('" + e + "i4', (2,)),('u1', (3,)),('" + e + "f4', (4, 2))], " +
- "'offsets':[0,12,20,24], 'itemsize':56}}").format(e=e),
+ (
+ "{{'names':['a','b','c','d'], "
+ + "'formats':[('S4', (3,)),('"
+ + e
+ + "i4', (2,)),('u1', (3,)),('"
+ + e
+ + "f4', (4, 2))], "
+ + "'offsets':[0,12,20,24], 'itemsize':56}}"
+ ).format(e=e),
"[('e1', '" + e + "i8'), ('e2', 'u1')]",
"[('x', 'i1'), ('y', '" + e + "u8')]",
- "[('cflt', '" + e + "c8'), ('cdbl', '" + e + "c16')]"
+ "[('cflt', '" + e + "c8'), ('cdbl', '" + e + "c16')]",
]
- d1 = np.dtype({'names': ['a', 'b'], 'formats': ['int32', 'float64'],
- 'offsets': [1, 10], 'itemsize': 20})
- d2 = np.dtype([('a', 'i4'), ('b', 'f4')])
- assert m.test_dtype_ctors() == [np.dtype('int32'), np.dtype('float64'),
- np.dtype('bool'), d1, d1, np.dtype('uint32'), d2]
+ d1 = np.dtype(
+ {
+ "names": ["a", "b"],
+ "formats": ["int32", "float64"],
+ "offsets": [1, 10],
+ "itemsize": 20,
+ }
+ )
+ d2 = np.dtype([("a", "i4"), ("b", "f4")])
+ assert m.test_dtype_ctors() == [
+ np.dtype("int32"),
+ np.dtype("float64"),
+ np.dtype("bool"),
+ d1,
+ d1,
+ np.dtype("uint32"),
+ d2,
+ ]
- assert m.test_dtype_methods() == [np.dtype('int32'), simple_dtype, False, True,
- np.dtype('int32').itemsize, simple_dtype.itemsize]
+ assert m.test_dtype_methods() == [
+ np.dtype("int32"),
+ simple_dtype,
+ False,
+ True,
+ np.dtype("int32").itemsize,
+ simple_dtype.itemsize,
+ ]
- assert m.trailing_padding_dtype() == m.buffer_to_dtype(np.zeros(1, m.trailing_padding_dtype()))
+ assert m.trailing_padding_dtype() == m.buffer_to_dtype(
+ np.zeros(1, m.trailing_padding_dtype())
+ )
def test_recarray(simple_dtype, packed_dtype):
elements = [(False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)]
- for func, dtype in [(m.create_rec_simple, simple_dtype), (m.create_rec_packed, packed_dtype)]:
+ for func, dtype in [
+ (m.create_rec_simple, simple_dtype),
+ (m.create_rec_packed, packed_dtype),
+ ]:
arr = func(0)
assert arr.dtype == dtype
assert_equal(arr, [], simple_dtype)
@@ -136,20 +187,24 @@ def test_recarray(simple_dtype, packed_dtype):
assert_equal(arr, elements, simple_dtype)
assert_equal(arr, elements, packed_dtype)
+ # Show what recarray's look like in NumPy.
+ assert type(arr[0]) == np.void
+ assert type(arr[0].item()) == tuple
+
if dtype == simple_dtype:
assert m.print_rec_simple(arr) == [
"s:0,0,0,-0",
"s:1,1,1.5,-2.5",
- "s:0,2,3,-5"
+ "s:0,2,3,-5",
]
else:
assert m.print_rec_packed(arr) == [
"p:0,0,0,-0",
"p:1,1,1.5,-2.5",
- "p:0,2,3,-5"
+ "p:0,2,3,-5",
]
- nested_dtype = np.dtype([('a', simple_dtype), ('b', packed_dtype)])
+ nested_dtype = np.dtype([("a", simple_dtype), ("b", packed_dtype)])
arr = m.create_rec_nested(0)
assert arr.dtype == nested_dtype
@@ -157,33 +212,39 @@ def test_recarray(simple_dtype, packed_dtype):
arr = m.create_rec_nested(3)
assert arr.dtype == nested_dtype
- assert_equal(arr, [((False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5)),
- ((True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)),
- ((False, 2, 3.0, -5.0), (True, 3, 4.5, -7.5))], nested_dtype)
+ assert_equal(
+ arr,
+ [
+ ((False, 0, 0.0, -0.0), (True, 1, 1.5, -2.5)),
+ ((True, 1, 1.5, -2.5), (False, 2, 3.0, -5.0)),
+ ((False, 2, 3.0, -5.0), (True, 3, 4.5, -7.5)),
+ ],
+ nested_dtype,
+ )
assert m.print_rec_nested(arr) == [
"n:a=s:0,0,0,-0;b=p:1,1,1.5,-2.5",
"n:a=s:1,1,1.5,-2.5;b=p:0,2,3,-5",
- "n:a=s:0,2,3,-5;b=p:1,3,4.5,-7.5"
+ "n:a=s:0,2,3,-5;b=p:1,3,4.5,-7.5",
]
arr = m.create_rec_partial(3)
assert str(arr.dtype) == partial_dtype_fmt()
partial_dtype = arr.dtype
- assert '' not in arr.dtype.fields
+ assert "" not in arr.dtype.fields
assert partial_dtype.itemsize > simple_dtype.itemsize
assert_equal(arr, elements, simple_dtype)
assert_equal(arr, elements, packed_dtype)
arr = m.create_rec_partial_nested(3)
assert str(arr.dtype) == partial_nested_fmt()
- assert '' not in arr.dtype.fields
- assert '' not in arr.dtype.fields['a'][0].fields
+ assert "" not in arr.dtype.fields
+ assert "" not in arr.dtype.fields["a"][0].fields
assert arr.dtype.itemsize > partial_dtype.itemsize
- np.testing.assert_equal(arr['a'], m.create_rec_partial(3))
+ np.testing.assert_equal(arr["a"], m.create_rec_partial(3))
def test_array_constructors():
- data = np.arange(1, 7, dtype='int32')
+ data = np.arange(1, 7, dtype="int32")
for i in range(8):
np.testing.assert_array_equal(m.test_array_ctors(10 + i), data.reshape((3, 2)))
np.testing.assert_array_equal(m.test_array_ctors(20 + i), data.reshape((3, 2)))
@@ -199,82 +260,92 @@ def test_string_array():
"a='',b=''",
"a='a',b='a'",
"a='ab',b='ab'",
- "a='abc',b='abc'"
+ "a='abc',b='abc'",
]
dtype = arr.dtype
- assert arr['a'].tolist() == [b'', b'a', b'ab', b'abc']
- assert arr['b'].tolist() == [b'', b'a', b'ab', b'abc']
+ assert arr["a"].tolist() == [b"", b"a", b"ab", b"abc"]
+ assert arr["b"].tolist() == [b"", b"a", b"ab", b"abc"]
arr = m.create_string_array(False)
assert dtype == arr.dtype
def test_array_array():
from sys import byteorder
- e = '<' if byteorder == 'little' else '>'
+
+ e = "<" if byteorder == "little" else ">"
arr = m.create_array_array(3)
assert str(arr.dtype) == (
- "{{'names':['a','b','c','d'], " +
- "'formats':[('S4', (3,)),('" + e + "i4', (2,)),('u1', (3,)),('{e}f4', (4, 2))], " +
- "'offsets':[0,12,20,24], 'itemsize':56}}").format(e=e)
+ "{{'names':['a','b','c','d'], "
+ + "'formats':[('S4', (3,)),('"
+ + e
+ + "i4', (2,)),('u1', (3,)),('{e}f4', (4, 2))], "
+ + "'offsets':[0,12,20,24], 'itemsize':56}}"
+ ).format(e=e)
assert m.print_array_array(arr) == [
- "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1}," +
- "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}",
- "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001}," +
- "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}",
- "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001}," +
- "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}",
+ "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1},"
+ + "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}",
+ "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001},"
+ + "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}",
+ "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001},"
+ + "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}",
+ ]
+ assert arr["a"].tolist() == [
+ [b"ABCD", b"KLMN", b"UVWX"],
+ [b"WXYZ", b"GHIJ", b"QRST"],
+ [b"STUV", b"CDEF", b"MNOP"],
]
- assert arr['a'].tolist() == [[b'ABCD', b'KLMN', b'UVWX'],
- [b'WXYZ', b'GHIJ', b'QRST'],
- [b'STUV', b'CDEF', b'MNOP']]
- assert arr['b'].tolist() == [[0, 1], [1000, 1001], [2000, 2001]]
+ assert arr["b"].tolist() == [[0, 1], [1000, 1001], [2000, 2001]]
assert m.create_array_array(0).dtype == arr.dtype
def test_enum_array():
from sys import byteorder
- e = '<' if byteorder == 'little' else '>'
+
+ e = "<" if byteorder == "little" else ">"
arr = m.create_enum_array(3)
dtype = arr.dtype
- assert dtype == np.dtype([('e1', e + 'i8'), ('e2', 'u1')])
- assert m.print_enum_array(arr) == [
- "e1=A,e2=X",
- "e1=B,e2=Y",
- "e1=A,e2=X"
- ]
- assert arr['e1'].tolist() == [-1, 1, -1]
- assert arr['e2'].tolist() == [1, 2, 1]
+ assert dtype == np.dtype([("e1", e + "i8"), ("e2", "u1")])
+ assert m.print_enum_array(arr) == ["e1=A,e2=X", "e1=B,e2=Y", "e1=A,e2=X"]
+ assert arr["e1"].tolist() == [-1, 1, -1]
+ assert arr["e2"].tolist() == [1, 2, 1]
assert m.create_enum_array(0).dtype == dtype
def test_complex_array():
from sys import byteorder
- e = '<' if byteorder == 'little' else '>'
+
+ e = "<" if byteorder == "little" else ">"
arr = m.create_complex_array(3)
dtype = arr.dtype
- assert dtype == np.dtype([('cflt', e + 'c8'), ('cdbl', e + 'c16')])
+ assert dtype == np.dtype([("cflt", e + "c8"), ("cdbl", e + "c16")])
assert m.print_complex_array(arr) == [
"c:(0,0.25),(0.5,0.75)",
"c:(1,1.25),(1.5,1.75)",
- "c:(2,2.25),(2.5,2.75)"
+ "c:(2,2.25),(2.5,2.75)",
]
- assert arr['cflt'].tolist() == [0.0 + 0.25j, 1.0 + 1.25j, 2.0 + 2.25j]
- assert arr['cdbl'].tolist() == [0.5 + 0.75j, 1.5 + 1.75j, 2.5 + 2.75j]
+ assert arr["cflt"].tolist() == [0.0 + 0.25j, 1.0 + 1.25j, 2.0 + 2.25j]
+ assert arr["cdbl"].tolist() == [0.5 + 0.75j, 1.5 + 1.75j, 2.5 + 2.75j]
assert m.create_complex_array(0).dtype == dtype
def test_signature(doc):
- assert doc(m.create_rec_nested) == \
- "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]"
+ assert (
+ doc(m.create_rec_nested)
+ == "create_rec_nested(arg0: int) -> numpy.ndarray[NestedStruct]"
+ )
def test_scalar_conversion():
n = 3
- arrays = [m.create_rec_simple(n), m.create_rec_packed(n),
- m.create_rec_nested(n), m.create_enum_array(n)]
+ arrays = [
+ m.create_rec_simple(n),
+ m.create_rec_packed(n),
+ m.create_rec_nested(n),
+ m.create_enum_array(n),
+ ]
funcs = [m.f_simple, m.f_packed, m.f_nested]
for i, func in enumerate(funcs):
@@ -284,18 +355,68 @@ def test_scalar_conversion():
else:
with pytest.raises(TypeError) as excinfo:
func(arr[0])
- assert 'incompatible function arguments' in str(excinfo.value)
+ assert "incompatible function arguments" in str(excinfo.value)
+
+
+def test_vectorize():
+ n = 3
+ array = m.create_rec_simple(n)
+ values = m.f_simple_vectorized(array)
+ np.testing.assert_array_equal(values, [0, 10, 20])
+ array_2 = m.f_simple_pass_thru_vectorized(array)
+ np.testing.assert_array_equal(array, array_2)
+
+
+def test_cls_and_dtype_conversion(simple_dtype):
+ s = m.SimpleStruct()
+ assert s.astuple() == (False, 0, 0.0, 0.0)
+ assert m.SimpleStruct.fromtuple(s.astuple()).astuple() == s.astuple()
+
+ s.uint_ = 2
+ assert m.f_simple(s) == 20
+
+ # Try as recarray of shape==(1,).
+ s_recarray = np.array([(False, 2, 0.0, 0.0)], dtype=simple_dtype)
+ # Show that this will work for vectorized case.
+ np.testing.assert_array_equal(m.f_simple_vectorized(s_recarray), [20])
+
+ # Show as a scalar that inherits from np.generic.
+ s_scalar = s_recarray[0]
+ assert isinstance(s_scalar, np.void)
+ assert m.f_simple(s_scalar) == 20
+
+ # Show that an *array* scalar (np.ndarray.shape == ()) does not convert.
+ # More specifically, conversion to SimpleStruct is not implicit.
+ s_recarray_scalar = s_recarray.reshape(())
+ assert isinstance(s_recarray_scalar, np.ndarray)
+ assert s_recarray_scalar.dtype == simple_dtype
+ with pytest.raises(TypeError) as excinfo:
+ m.f_simple(s_recarray_scalar)
+ assert "incompatible function arguments" in str(excinfo.value)
+ # Explicitly convert to m.SimpleStruct.
+ assert m.f_simple(m.SimpleStruct.fromtuple(s_recarray_scalar.item())) == 20
+
+ # Show that an array of dtype=object does *not* convert.
+ s_array_object = np.array([s])
+ assert s_array_object.dtype == object
+ with pytest.raises(TypeError) as excinfo:
+ m.f_simple_vectorized(s_array_object)
+ assert "incompatible function arguments" in str(excinfo.value)
+ # Explicitly convert to `np.array(..., dtype=simple_dtype)`
+ s_array = np.array([s.astuple()], dtype=simple_dtype)
+ np.testing.assert_array_equal(m.f_simple_vectorized(s_array), [20])
def test_register_dtype():
with pytest.raises(RuntimeError) as excinfo:
m.register_dtype()
- assert 'dtype is already registered' in str(excinfo.value)
+ assert "dtype is already registered" in str(excinfo.value)
-@pytest.unsupported_on_pypy
+@pytest.mark.xfail("env.PYPY")
def test_str_leak():
from sys import getrefcount
+
fmt = "f4"
pytest.gc_collect()
start = getrefcount(fmt)
diff --git a/3rdparty/pybind11/tests/test_numpy_vectorize.cpp b/3rdparty/pybind11/tests/test_numpy_vectorize.cpp
index a875a74b..274b7558 100644
--- a/3rdparty/pybind11/tests/test_numpy_vectorize.cpp
+++ b/3rdparty/pybind11/tests/test_numpy_vectorize.cpp
@@ -17,7 +17,7 @@ double my_func(int x, float y, double z) {
}
TEST_SUBMODULE(numpy_vectorize, m) {
- try { py::module::import("numpy"); }
+ try { py::module_::import("numpy"); }
catch (...) { return; }
// test_vectorize, test_docs, test_array_collapse
@@ -37,7 +37,7 @@ TEST_SUBMODULE(numpy_vectorize, m) {
));
// test_type_selection
- // Numpy function which only accepts specific data types
+ // NumPy function which only accepts specific data types
m.def("selective_func", [](py::array_t<int, py::array::c_style>) { return "Int branch taken."; });
m.def("selective_func", [](py::array_t<float, py::array::c_style>) { return "Float branch taken."; });
m.def("selective_func", [](py::array_t<std::complex<float>, py::array::c_style>) { return "Complex float branch taken."; });
@@ -50,7 +50,9 @@ TEST_SUBMODULE(numpy_vectorize, m) {
NonPODClass(int v) : value{v} {}
int value;
};
- py::class_<NonPODClass>(m, "NonPODClass").def(py::init<int>());
+ py::class_<NonPODClass>(m, "NonPODClass")
+ .def(py::init<int>())
+ .def_readwrite("value", &NonPODClass::value);
m.def("vec_passthrough", py::vectorize(
[](double *a, double b, py::array_t<double> c, const int &d, int &e, NonPODClass f, const double g) {
return *a + b + c.at(0) + d + e + f.value + g;
@@ -81,9 +83,11 @@ TEST_SUBMODULE(numpy_vectorize, m) {
py::array_t<float, py::array::forcecast> arg2,
py::array_t<double, py::array::forcecast> arg3
) {
- ssize_t ndim;
- std::vector<ssize_t> shape;
+ py::ssize_t ndim;
+ std::vector<py::ssize_t> shape;
std::array<py::buffer_info, 3> buffers {{ arg1.request(), arg2.request(), arg3.request() }};
return py::detail::broadcast(buffers, ndim, shape);
});
+
+ m.def("add_to", py::vectorize([](NonPODClass& x, int a) { x.value += a; }));
}
diff --git a/3rdparty/pybind11/tests/test_numpy_vectorize.py b/3rdparty/pybind11/tests/test_numpy_vectorize.py
index 0e9c8839..4e6b2d19 100644
--- a/3rdparty/pybind11/tests/test_numpy_vectorize.py
+++ b/3rdparty/pybind11/tests/test_numpy_vectorize.py
@@ -1,10 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import numpy_vectorize as m
-pytestmark = pytest.requires_numpy
-
-with pytest.suppress(ImportError):
- import numpy as np
+np = pytest.importorskip("numpy")
def test_vectorize(capture):
@@ -19,28 +17,40 @@ def test_vectorize(capture):
assert capture == "my_func(x:int=1, y:float=2, z:float=3)"
with capture:
assert np.allclose(f(np.array([1, 3]), np.array([2, 4]), 3), [6, 36])
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=3)
my_func(x:int=3, y:float=4, z:float=3)
"""
+ )
with capture:
- a = np.array([[1, 2], [3, 4]], order='F')
- b = np.array([[10, 20], [30, 40]], order='F')
+ a = np.array([[1, 2], [3, 4]], order="F")
+ b = np.array([[10, 20], [30, 40]], order="F")
c = 3
result = f(a, b, c)
assert np.allclose(result, a * b * c)
assert result.flags.f_contiguous
# All inputs are F order and full or singletons, so we the result is in col-major order:
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=10, z:float=3)
my_func(x:int=3, y:float=30, z:float=3)
my_func(x:int=2, y:float=20, z:float=3)
my_func(x:int=4, y:float=40, z:float=3)
"""
+ )
with capture:
- a, b, c = np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3
+ a, b, c = (
+ np.array([[1, 3, 5], [7, 9, 11]]),
+ np.array([[2, 4, 6], [8, 10, 12]]),
+ 3,
+ )
assert np.allclose(f(a, b, c), a * b * c)
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=3)
my_func(x:int=3, y:float=4, z:float=3)
my_func(x:int=5, y:float=6, z:float=3)
@@ -48,10 +58,13 @@ def test_vectorize(capture):
my_func(x:int=9, y:float=10, z:float=3)
my_func(x:int=11, y:float=12, z:float=3)
"""
+ )
with capture:
a, b, c = np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2
assert np.allclose(f(a, b, c), a * b * c)
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=2)
my_func(x:int=2, y:float=3, z:float=2)
my_func(x:int=3, y:float=4, z:float=2)
@@ -59,10 +72,13 @@ def test_vectorize(capture):
my_func(x:int=5, y:float=3, z:float=2)
my_func(x:int=6, y:float=4, z:float=2)
"""
+ )
with capture:
a, b, c = np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2
assert np.allclose(f(a, b, c), a * b * c)
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=2)
my_func(x:int=2, y:float=2, z:float=2)
my_func(x:int=3, y:float=2, z:float=2)
@@ -70,10 +86,17 @@ def test_vectorize(capture):
my_func(x:int=5, y:float=3, z:float=2)
my_func(x:int=6, y:float=3, z:float=2)
"""
+ )
with capture:
- a, b, c = np.array([[1, 2, 3], [4, 5, 6]], order='F'), np.array([[2], [3]]), 2
+ a, b, c = (
+ np.array([[1, 2, 3], [4, 5, 6]], order="F"),
+ np.array([[2], [3]]),
+ 2,
+ )
assert np.allclose(f(a, b, c), a * b * c)
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=2)
my_func(x:int=2, y:float=2, z:float=2)
my_func(x:int=3, y:float=2, z:float=2)
@@ -81,36 +104,53 @@ def test_vectorize(capture):
my_func(x:int=5, y:float=3, z:float=2)
my_func(x:int=6, y:float=3, z:float=2)
"""
+ )
with capture:
a, b, c = np.array([[1, 2, 3], [4, 5, 6]])[::, ::2], np.array([[2], [3]]), 2
assert np.allclose(f(a, b, c), a * b * c)
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=2)
my_func(x:int=3, y:float=2, z:float=2)
my_func(x:int=4, y:float=3, z:float=2)
my_func(x:int=6, y:float=3, z:float=2)
"""
+ )
with capture:
- a, b, c = np.array([[1, 2, 3], [4, 5, 6]], order='F')[::, ::2], np.array([[2], [3]]), 2
+ a, b, c = (
+ np.array([[1, 2, 3], [4, 5, 6]], order="F")[::, ::2],
+ np.array([[2], [3]]),
+ 2,
+ )
assert np.allclose(f(a, b, c), a * b * c)
- assert capture == """
+ assert (
+ capture
+ == """
my_func(x:int=1, y:float=2, z:float=2)
my_func(x:int=3, y:float=2, z:float=2)
my_func(x:int=4, y:float=3, z:float=2)
my_func(x:int=6, y:float=3, z:float=2)
"""
+ )
def test_type_selection():
assert m.selective_func(np.array([1], dtype=np.int32)) == "Int branch taken."
assert m.selective_func(np.array([1.0], dtype=np.float32)) == "Float branch taken."
- assert m.selective_func(np.array([1.0j], dtype=np.complex64)) == "Complex float branch taken."
+ assert (
+ m.selective_func(np.array([1.0j], dtype=np.complex64))
+ == "Complex float branch taken."
+ )
def test_docs(doc):
- assert doc(m.vectorized_func) == """
- vectorized_func(arg0: numpy.ndarray[int32], arg1: numpy.ndarray[float32], arg2: numpy.ndarray[float64]) -> object
+ assert (
+ doc(m.vectorized_func)
+ == """
+ vectorized_func(arg0: numpy.ndarray[numpy.int32], arg1: numpy.ndarray[numpy.float32], arg2: numpy.ndarray[numpy.float64]) -> object
""" # noqa: E501 line too long
+ )
def test_trivial_broadcasting():
@@ -118,16 +158,24 @@ def test_trivial_broadcasting():
assert vectorized_is_trivial(1, 2, 3) == trivial.c_trivial
assert vectorized_is_trivial(np.array(1), np.array(2), 3) == trivial.c_trivial
- assert vectorized_is_trivial(np.array([1, 3]), np.array([2, 4]), 3) == trivial.c_trivial
+ assert (
+ vectorized_is_trivial(np.array([1, 3]), np.array([2, 4]), 3)
+ == trivial.c_trivial
+ )
assert trivial.c_trivial == vectorized_is_trivial(
- np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3)
- assert vectorized_is_trivial(
- np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2) == trivial.non_trivial
- assert vectorized_is_trivial(
- np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2) == trivial.non_trivial
- z1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype='int32')
- z2 = np.array(z1, dtype='float32')
- z3 = np.array(z1, dtype='float64')
+ np.array([[1, 3, 5], [7, 9, 11]]), np.array([[2, 4, 6], [8, 10, 12]]), 3
+ )
+ assert (
+ vectorized_is_trivial(np.array([[1, 2, 3], [4, 5, 6]]), np.array([2, 3, 4]), 2)
+ == trivial.non_trivial
+ )
+ assert (
+ vectorized_is_trivial(np.array([[1, 2, 3], [4, 5, 6]]), np.array([[2], [3]]), 2)
+ == trivial.non_trivial
+ )
+ z1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]], dtype="int32")
+ z2 = np.array(z1, dtype="float32")
+ z3 = np.array(z1, dtype="float64")
assert vectorized_is_trivial(z1, z2, z3) == trivial.c_trivial
assert vectorized_is_trivial(1, z2, z3) == trivial.c_trivial
assert vectorized_is_trivial(z1, 1, z3) == trivial.c_trivial
@@ -137,7 +185,7 @@ def test_trivial_broadcasting():
assert vectorized_is_trivial(1, 1, z3[::2, ::2]) == trivial.non_trivial
assert vectorized_is_trivial(z1, 1, z3[1::4, 1::4]) == trivial.c_trivial
- y1 = np.array(z1, order='F')
+ y1 = np.array(z1, order="F")
y2 = np.array(y1)
y3 = np.array(y1)
assert vectorized_is_trivial(y1, y2, y3) == trivial.f_trivial
@@ -158,30 +206,41 @@ def test_trivial_broadcasting():
def test_passthrough_arguments(doc):
assert doc(m.vec_passthrough) == (
- "vec_passthrough(" + ", ".join([
- "arg0: float",
- "arg1: numpy.ndarray[float64]",
- "arg2: numpy.ndarray[float64]",
- "arg3: numpy.ndarray[int32]",
- "arg4: int",
- "arg5: m.numpy_vectorize.NonPODClass",
- "arg6: numpy.ndarray[float64]"]) + ") -> object")
-
- b = np.array([[10, 20, 30]], dtype='float64')
+ "vec_passthrough("
+ + ", ".join(
+ [
+ "arg0: float",
+ "arg1: numpy.ndarray[numpy.float64]",
+ "arg2: numpy.ndarray[numpy.float64]",
+ "arg3: numpy.ndarray[numpy.int32]",
+ "arg4: int",
+ "arg5: m.numpy_vectorize.NonPODClass",
+ "arg6: numpy.ndarray[numpy.float64]",
+ ]
+ )
+ + ") -> object"
+ )
+
+ b = np.array([[10, 20, 30]], dtype="float64")
c = np.array([100, 200]) # NOT a vectorized argument
- d = np.array([[1000], [2000], [3000]], dtype='int')
- g = np.array([[1000000, 2000000, 3000000]], dtype='int') # requires casting
+ d = np.array([[1000], [2000], [3000]], dtype="int")
+ g = np.array([[1000000, 2000000, 3000000]], dtype="int") # requires casting
assert np.all(
- m.vec_passthrough(1, b, c, d, 10000, m.NonPODClass(100000), g) ==
- np.array([[1111111, 2111121, 3111131],
- [1112111, 2112121, 3112131],
- [1113111, 2113121, 3113131]]))
+ m.vec_passthrough(1, b, c, d, 10000, m.NonPODClass(100000), g)
+ == np.array(
+ [
+ [1111111, 2111121, 3111131],
+ [1112111, 2112121, 3112131],
+ [1113111, 2113121, 3113131],
+ ]
+ )
+ )
def test_method_vectorization():
o = m.VectorizeTestClass(3)
- x = np.array([1, 2], dtype='int')
- y = np.array([[10], [20]], dtype='float32')
+ x = np.array([1, 2], dtype="int")
+ y = np.array([[10], [20]], dtype="float32")
assert np.all(o.method(x, y) == [[14, 15], [24, 25]])
@@ -190,7 +249,18 @@ def test_array_collapse():
assert not isinstance(m.vectorized_func(np.array(1), 2, 3), np.ndarray)
z = m.vectorized_func([1], 2, 3)
assert isinstance(z, np.ndarray)
- assert z.shape == (1, )
+ assert z.shape == (1,)
z = m.vectorized_func(1, [[[2]]], 3)
assert isinstance(z, np.ndarray)
assert z.shape == (1, 1, 1)
+
+
+def test_vectorized_noreturn():
+ x = m.NonPODClass(0)
+ assert x.value == 0
+ m.add_to(x, [1, 2, 3, 4])
+ assert x.value == 10
+ m.add_to(x, 1)
+ assert x.value == 11
+ m.add_to(x, [[1, 1], [2, 3]])
+ assert x.value == 18
diff --git a/3rdparty/pybind11/tests/test_opaque_types.cpp b/3rdparty/pybind11/tests/test_opaque_types.cpp
index 0d20d9a0..5a234316 100644
--- a/3rdparty/pybind11/tests/test_opaque_types.cpp
+++ b/3rdparty/pybind11/tests/test_opaque_types.cpp
@@ -60,8 +60,14 @@ TEST_SUBMODULE(opaque_types, m) {
m.def("get_null_str_value", [](char *ptr) { return reinterpret_cast<std::intptr_t>(ptr); });
m.def("return_unique_ptr", []() -> std::unique_ptr<StringList> {
- StringList *result = new StringList();
+ auto *result = new StringList();
result->push_back("some value");
return std::unique_ptr<StringList>(result);
});
+
+ // test unions
+ py::class_<IntFloat>(m, "IntFloat")
+ .def(py::init<>())
+ .def_readwrite("i", &IntFloat::i)
+ .def_readwrite("f", &IntFloat::f);
}
diff --git a/3rdparty/pybind11/tests/test_opaque_types.py b/3rdparty/pybind11/tests/test_opaque_types.py
index 6b3802fd..77379463 100644
--- a/3rdparty/pybind11/tests/test_opaque_types.py
+++ b/3rdparty/pybind11/tests/test_opaque_types.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import opaque_types as m
from pybind11_tests import ConstructorStats, UserType
@@ -31,12 +32,15 @@ def test_pointers(msg):
with pytest.raises(TypeError) as excinfo:
m.get_void_ptr_value([1, 2, 3]) # This should not work
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
get_void_ptr_value(): incompatible function arguments. The following argument types are supported:
1. (arg0: capsule) -> int
Invoked with: [1, 2, 3]
""" # noqa: E501 line too long
+ )
assert m.return_null_str() is None
assert m.get_null_str_value(m.return_null_str()) is not None
@@ -44,3 +48,11 @@ def test_pointers(msg):
ptr = m.return_unique_ptr()
assert "StringList" in repr(ptr)
assert m.print_opaque_list(ptr) == "Opaque list: [some value]"
+
+
+def test_unions():
+ int_float_union = m.IntFloat()
+ int_float_union.i = 42
+ assert int_float_union.i == 42
+ int_float_union.f = 3.0
+ assert int_float_union.f == 3.0
diff --git a/3rdparty/pybind11/tests/test_operator_overloading.cpp b/3rdparty/pybind11/tests/test_operator_overloading.cpp
index 7b111704..0a27bfd5 100644
--- a/3rdparty/pybind11/tests/test_operator_overloading.cpp
+++ b/3rdparty/pybind11/tests/test_operator_overloading.cpp
@@ -43,6 +43,13 @@ public:
friend Vector2 operator-(float f, const Vector2 &v) { return Vector2(f - v.x, f - v.y); }
friend Vector2 operator*(float f, const Vector2 &v) { return Vector2(f * v.x, f * v.y); }
friend Vector2 operator/(float f, const Vector2 &v) { return Vector2(f / v.x, f / v.y); }
+
+ bool operator==(const Vector2 &v) const {
+ return x == v.x && y == v.y;
+ }
+ bool operator!=(const Vector2 &v) const {
+ return x != v.x || y != v.y;
+ }
private:
float x, y;
};
@@ -55,12 +62,22 @@ int operator+(const C2 &, const C2 &) { return 22; }
int operator+(const C2 &, const C1 &) { return 21; }
int operator+(const C1 &, const C2 &) { return 12; }
+// Note: Specializing explicit within `namespace std { ... }` is done due to a
+// bug in GCC<7. If you are supporting compilers later than this, consider
+// specializing `using template<> struct std::hash<...>` in the global
+// namespace instead, per this recommendation:
+// https://en.cppreference.com/w/cpp/language/extending_std#Adding_template_specializations
namespace std {
template<>
struct hash<Vector2> {
// Not a good hash function, but easy to test
size_t operator()(const Vector2 &) { return 4; }
};
+} // namespace std
+
+// Not a good abs function, but easy to test.
+std::string abs(const Vector2&) {
+ return "abs(Vector2)";
}
// MSVC warns about unknown pragmas, and warnings are errors.
@@ -71,11 +88,11 @@ namespace std {
// Here, we suppress the warning using `#pragma diagnostic`.
// Taken from: https://github.com/RobotLocomotion/drake/commit/aaf84b46
// TODO(eric): This could be resolved using a function / functor (e.g. `py::self()`).
- #if (__APPLE__) && (__clang__)
- #if (__clang_major__ >= 10) && (__clang_minor__ >= 0) && (__clang_patchlevel__ >= 1)
+ #if defined(__APPLE__) && defined(__clang__)
+ #if (__clang_major__ >= 10)
#pragma GCC diagnostic ignored "-Wself-assign-overloaded"
#endif
- #elif (__clang__)
+ #elif defined(__clang__)
#if (__clang_major__ >= 7)
#pragma GCC diagnostic ignored "-Wself-assign-overloaded"
#endif
@@ -107,7 +124,13 @@ TEST_SUBMODULE(operators, m) {
.def(float() / py::self)
.def(-py::self)
.def("__str__", &Vector2::toString)
- .def(hash(py::self))
+ .def("__repr__", &Vector2::toString)
+ .def(py::self == py::self)
+ .def(py::self != py::self)
+ .def(py::hash(py::self))
+ // N.B. See warning about usage of `py::detail::abs(py::self)` in
+ // `operators.h`.
+ .def("__abs__", [](const Vector2& v) { return abs(v); })
;
m.attr("Vector") = m.attr("Vector2");
@@ -164,6 +187,38 @@ TEST_SUBMODULE(operators, m) {
.def(py::self *= int())
.def_readwrite("b", &NestC::b);
m.def("get_NestC", [](const NestC &c) { return c.value; });
+
+
+ // test_overriding_eq_reset_hash
+ // #2191 Overriding __eq__ should set __hash__ to None
+ struct Comparable {
+ int value;
+ bool operator==(const Comparable& rhs) const {return value == rhs.value;}
+ };
+
+ struct Hashable : Comparable {
+ explicit Hashable(int value): Comparable{value}{};
+ size_t hash() const { return static_cast<size_t>(value); }
+ };
+
+ struct Hashable2 : Hashable {
+ using Hashable::Hashable;
+ };
+
+ py::class_<Comparable>(m, "Comparable")
+ .def(py::init<int>())
+ .def(py::self == py::self);
+
+ py::class_<Hashable>(m, "Hashable")
+ .def(py::init<int>())
+ .def(py::self == py::self)
+ .def("__hash__", &Hashable::hash);
+
+ // define __hash__ before __eq__
+ py::class_<Hashable2>(m, "Hashable2")
+ .def("__hash__", &Hashable::hash)
+ .def(py::init<int>())
+ .def(py::self == py::self);
}
#ifndef _MSC_VER
diff --git a/3rdparty/pybind11/tests/test_operator_overloading.py b/3rdparty/pybind11/tests/test_operator_overloading.py
index bd36ac2a..5dbfb32c 100644
--- a/3rdparty/pybind11/tests/test_operator_overloading.py
+++ b/3rdparty/pybind11/tests/test_operator_overloading.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import operators as m
from pybind11_tests import ConstructorStats
@@ -6,6 +7,9 @@ from pybind11_tests import ConstructorStats
def test_operator_overloading():
v1 = m.Vector2(1, 2)
v2 = m.Vector(3, -1)
+ v3 = m.Vector2(1, 2) # Same value as v1, but different instance.
+ assert v1 is not v3
+
assert str(v1) == "[1.000000, 2.000000]"
assert str(v2) == "[3.000000, -1.000000]"
@@ -24,6 +28,12 @@ def test_operator_overloading():
assert str(v1 * v2) == "[3.000000, -2.000000]"
assert str(v2 / v1) == "[3.000000, -0.500000]"
+ assert v1 == v3
+ assert v1 != v2
+ assert hash(v1) == 4
+ # TODO(eric.cousineau): Make this work.
+ # assert abs(v1) == "abs(Vector2)"
+
v1 += 2 * v2
assert str(v1) == "[7.000000, 0.000000]"
v1 -= v2
@@ -37,22 +47,33 @@ def test_operator_overloading():
v2 /= v1
assert str(v2) == "[2.000000, 8.000000]"
- assert hash(v1) == 4
-
cstats = ConstructorStats.get(m.Vector2)
- assert cstats.alive() == 2
+ assert cstats.alive() == 3
del v1
- assert cstats.alive() == 1
+ assert cstats.alive() == 2
del v2
+ assert cstats.alive() == 1
+ del v3
assert cstats.alive() == 0
- assert cstats.values() == ['[1.000000, 2.000000]', '[3.000000, -1.000000]',
- '[-3.000000, 1.000000]', '[4.000000, 1.000000]',
- '[-2.000000, 3.000000]', '[-7.000000, -6.000000]',
- '[9.000000, 10.000000]', '[8.000000, 16.000000]',
- '[0.125000, 0.250000]', '[7.000000, 6.000000]',
- '[9.000000, 10.000000]', '[8.000000, 16.000000]',
- '[8.000000, 4.000000]', '[3.000000, -2.000000]',
- '[3.000000, -0.500000]', '[6.000000, -2.000000]']
+ assert cstats.values() == [
+ "[1.000000, 2.000000]",
+ "[3.000000, -1.000000]",
+ "[1.000000, 2.000000]",
+ "[-3.000000, 1.000000]",
+ "[4.000000, 1.000000]",
+ "[-2.000000, 3.000000]",
+ "[-7.000000, -6.000000]",
+ "[9.000000, 10.000000]",
+ "[8.000000, 16.000000]",
+ "[0.125000, 0.250000]",
+ "[7.000000, 6.000000]",
+ "[9.000000, 10.000000]",
+ "[8.000000, 16.000000]",
+ "[8.000000, 4.000000]",
+ "[3.000000, -2.000000]",
+ "[3.000000, -0.500000]",
+ "[6.000000, -2.000000]",
+ ]
assert cstats.default_constructions == 0
assert cstats.copy_constructions == 0
assert cstats.move_constructions >= 10
@@ -106,3 +127,19 @@ def test_nested():
assert abase.value == 42
del abase, b
pytest.gc_collect()
+
+
+def test_overriding_eq_reset_hash():
+
+ assert m.Comparable(15) is not m.Comparable(15)
+ assert m.Comparable(15) == m.Comparable(15)
+
+ with pytest.raises(TypeError):
+ hash(m.Comparable(15)) # TypeError: unhashable type: 'm.Comparable'
+
+ for hashable in (m.Hashable, m.Hashable2):
+ assert hashable(15) is not hashable(15)
+ assert hashable(15) == hashable(15)
+
+ assert hash(hashable(15)) == 15
+ assert hash(hashable(15)) == hash(hashable(15))
diff --git a/3rdparty/pybind11/tests/test_pickling.py b/3rdparty/pybind11/tests/test_pickling.py
index 5ae05aaa..6b27a73a 100644
--- a/3rdparty/pybind11/tests/test_pickling.py
+++ b/3rdparty/pybind11/tests/test_pickling.py
@@ -1,4 +1,8 @@
+# -*- coding: utf-8 -*-
import pytest
+
+import env # noqa: F401
+
from pybind11_tests import pickling as m
try:
@@ -21,7 +25,7 @@ def test_roundtrip(cls_name):
assert p2.extra2() == p.extra2()
-@pytest.unsupported_on_pypy
+@pytest.mark.xfail("env.PYPY")
@pytest.mark.parametrize("cls_name", ["PickleableWithDict", "PickleableWithDictNew"])
def test_roundtrip_with_dict(cls_name):
cls = getattr(m, cls_name)
@@ -38,5 +42,6 @@ def test_roundtrip_with_dict(cls_name):
def test_enum_pickle():
from pybind11_tests import enums as e
+
data = pickle.dumps(e.EOne, 2)
assert e.EOne == pickle.loads(data)
diff --git a/3rdparty/pybind11/tests/test_pytypes.cpp b/3rdparty/pybind11/tests/test_pytypes.cpp
index 244e1db0..113cf5cb 100644
--- a/3rdparty/pybind11/tests/test_pytypes.cpp
+++ b/3rdparty/pybind11/tests/test_pytypes.cpp
@@ -11,6 +11,12 @@
TEST_SUBMODULE(pytypes, m) {
+ // test_int
+ m.def("get_int", []{return py::int_(0);});
+ // test_iterator
+ m.def("get_iterator", []{return py::iterator();});
+ // test_iterable
+ m.def("get_iterable", []{return py::iterable();});
// test_list
m.def("get_list", []() {
py::list list;
@@ -26,6 +32,11 @@ TEST_SUBMODULE(pytypes, m) {
for (auto item : list)
py::print("list item {}: {}"_s.format(index++, item));
});
+ // test_none
+ m.def("get_none", []{return py::none();});
+ m.def("print_none", [](py::none none) {
+ py::print("none: {}"_s.format(none));
+ });
// test_set
m.def("get_set", []() {
@@ -69,6 +80,7 @@ TEST_SUBMODULE(pytypes, m) {
m.def("str_from_bytes", []() { return py::str(py::bytes("boo", 3)); });
m.def("str_from_object", [](const py::object& obj) { return py::str(obj); });
m.def("repr_from_object", [](const py::object& obj) { return py::repr(obj); });
+ m.def("str_from_handle", [](py::handle h) { return py::str(h); });
m.def("str_format", []() {
auto s1 = "{} + {} = {}"_s.format(1, 2, 3);
@@ -96,7 +108,7 @@ TEST_SUBMODULE(pytypes, m) {
});
m.def("return_capsule_with_name_and_destructor", []() {
- auto capsule = py::capsule((void *) 1234, "pointer type description", [](PyObject *ptr) {
+ auto capsule = py::capsule((void *) 12345, "pointer type description", [](PyObject *ptr) {
if (ptr) {
auto name = PyCapsule_GetName(ptr);
py::print("destructing capsule ({}, '{}')"_s.format(
@@ -104,8 +116,19 @@ TEST_SUBMODULE(pytypes, m) {
));
}
});
- void *contents = capsule;
- py::print("created capsule ({}, '{}')"_s.format((size_t) contents, capsule.name()));
+
+ capsule.set_pointer((void *) 1234);
+
+ // Using get_pointer<T>()
+ void* contents1 = static_cast<void*>(capsule);
+ void* contents2 = capsule.get_pointer();
+ void* contents3 = capsule.get_pointer<void>();
+
+ auto result1 = reinterpret_cast<size_t>(contents1);
+ auto result2 = reinterpret_cast<size_t>(contents2);
+ auto result3 = reinterpret_cast<size_t>(contents3);
+
+ py::print("created capsule ({}, '{}')"_s.format(result1 & result2 & result3, capsule.name()));
return capsule;
});
@@ -116,7 +139,7 @@ TEST_SUBMODULE(pytypes, m) {
d["basic_attr"] = o.attr("basic_attr");
auto l = py::list();
- for (const auto &item : o.attr("begin_end")) {
+ for (auto item : o.attr("begin_end")) {
l.append(item);
}
d["begin_end"] = l;
@@ -186,6 +209,7 @@ TEST_SUBMODULE(pytypes, m) {
// test_constructors
m.def("default_constructors", []() {
return py::dict(
+ "bytes"_a=py::bytes(),
"str"_a=py::str(),
"bool"_a=py::bool_(),
"int"_a=py::int_(),
@@ -199,6 +223,7 @@ TEST_SUBMODULE(pytypes, m) {
m.def("converting_constructors", [](py::dict d) {
return py::dict(
+ "bytes"_a=py::bytes(d["bytes"]),
"str"_a=py::str(d["str"]),
"bool"_a=py::bool_(d["bool"]),
"int"_a=py::int_(d["int"]),
@@ -214,6 +239,7 @@ TEST_SUBMODULE(pytypes, m) {
m.def("cast_functions", [](py::dict d) {
// When converting between Python types, obj.cast<T>() should be the same as T(obj)
return py::dict(
+ "bytes"_a=d["bytes"].cast<py::bytes>(),
"str"_a=d["str"].cast<py::str>(),
"bool"_a=d["bool"].cast<py::bool_>(),
"int"_a=d["int"].cast<py::int_>(),
@@ -226,6 +252,21 @@ TEST_SUBMODULE(pytypes, m) {
);
});
+ m.def("convert_to_pybind11_str", [](py::object o) { return py::str(o); });
+
+ m.def("nonconverting_constructor", [](std::string type, py::object value) -> py::object {
+ if (type == "bytes") {
+ return py::bytes(value);
+ }
+ else if (type == "none") {
+ return py::none(value);
+ }
+ else if (type == "ellipsis") {
+ return py::ellipsis(value);
+ }
+ throw std::runtime_error("Invalid type");
+ });
+
m.def("get_implicit_casting", []() {
py::dict d;
d["char*_i1"] = "abc";
@@ -272,7 +313,7 @@ TEST_SUBMODULE(pytypes, m) {
py::print("no new line here", "end"_a=" -- ");
py::print("next print");
- auto py_stderr = py::module::import("sys").attr("stderr");
+ auto py_stderr = py::module_::import("sys").attr("stderr");
py::print("this goes to stderr", "file"_a=py_stderr);
py::print("flush", "flush"_a=true);
@@ -307,4 +348,66 @@ TEST_SUBMODULE(pytypes, m) {
m.def("test_list_slicing", [](py::list a) {
return a[py::slice(0, -1, 2)];
});
+
+ // See #2361
+ m.def("issue2361_str_implicit_copy_none", []() {
+ py::str is_this_none = py::none();
+ return is_this_none;
+ });
+ m.def("issue2361_dict_implicit_copy_none", []() {
+ py::dict is_this_none = py::none();
+ return is_this_none;
+ });
+
+ m.def("test_memoryview_object", [](py::buffer b) {
+ return py::memoryview(b);
+ });
+
+ m.def("test_memoryview_buffer_info", [](py::buffer b) {
+ return py::memoryview(b.request());
+ });
+
+ m.def("test_memoryview_from_buffer", [](bool is_unsigned) {
+ static const int16_t si16[] = { 3, 1, 4, 1, 5 };
+ static const uint16_t ui16[] = { 2, 7, 1, 8 };
+ if (is_unsigned)
+ return py::memoryview::from_buffer(
+ ui16, { 4 }, { sizeof(uint16_t) });
+ else
+ return py::memoryview::from_buffer(
+ si16, { 5 }, { sizeof(int16_t) });
+ });
+
+ m.def("test_memoryview_from_buffer_nativeformat", []() {
+ static const char* format = "@i";
+ static const int32_t arr[] = { 4, 7, 5 };
+ return py::memoryview::from_buffer(
+ arr, sizeof(int32_t), format, { 3 }, { sizeof(int32_t) });
+ });
+
+ m.def("test_memoryview_from_buffer_empty_shape", []() {
+ static const char* buf = "";
+ return py::memoryview::from_buffer(buf, 1, "B", { }, { });
+ });
+
+ m.def("test_memoryview_from_buffer_invalid_strides", []() {
+ static const char* buf = "\x02\x03\x04";
+ return py::memoryview::from_buffer(buf, 1, "B", { 3 }, { });
+ });
+
+ m.def("test_memoryview_from_buffer_nullptr", []() {
+ return py::memoryview::from_buffer(
+ static_cast<void*>(nullptr), 1, "B", { }, { });
+ });
+
+#if PY_MAJOR_VERSION >= 3
+ m.def("test_memoryview_from_memory", []() {
+ const char* buf = "\xff\xe1\xab\x37";
+ return py::memoryview::from_memory(
+ buf, static_cast<py::ssize_t>(strlen(buf)));
+ });
+#endif
+
+ // test_builtin_functions
+ m.def("get_len", [](py::handle h) { return py::len(h); });
}
diff --git a/3rdparty/pybind11/tests/test_pytypes.py b/3rdparty/pybind11/tests/test_pytypes.py
index 0e8d6c33..9e5c302e 100644
--- a/3rdparty/pybind11/tests/test_pytypes.py
+++ b/3rdparty/pybind11/tests/test_pytypes.py
@@ -1,11 +1,26 @@
+# -*- coding: utf-8 -*-
from __future__ import division
import pytest
import sys
+import env # noqa: F401
+
from pybind11_tests import pytypes as m
from pybind11_tests import debug_enabled
+def test_int(doc):
+ assert doc(m.get_int) == "get_int() -> int"
+
+
+def test_iterator(doc):
+ assert doc(m.get_iterator) == "get_iterator() -> Iterator"
+
+
+def test_iterable(doc):
+ assert doc(m.get_iterable) == "get_iterable() -> Iterable"
+
+
def test_list(capture, doc):
with capture:
lst = m.get_list()
@@ -13,18 +28,26 @@ def test_list(capture, doc):
lst.append("value2")
m.print_list(lst)
- assert capture.unordered == """
+ assert (
+ capture.unordered
+ == """
Entry at position 0: value
list item 0: inserted-0
list item 1: overwritten
list item 2: inserted-2
list item 3: value2
"""
+ )
assert doc(m.get_list) == "get_list() -> list"
assert doc(m.print_list) == "print_list(arg0: list) -> None"
+def test_none(capture, doc):
+ assert doc(m.get_none) == "get_none() -> None"
+ assert doc(m.print_none) == "print_none(arg0: None) -> None"
+
+
def test_set(capture, doc):
s = m.get_set()
assert s == {"key1", "key2", "key3"}
@@ -32,12 +55,15 @@ def test_set(capture, doc):
with capture:
s.add("key4")
m.print_set(s)
- assert capture.unordered == """
+ assert (
+ capture.unordered
+ == """
key: key1
key: key2
key: key3
key: key4
"""
+ )
assert not m.set_contains(set([]), 42)
assert m.set_contains({42}, 42)
@@ -54,10 +80,13 @@ def test_dict(capture, doc):
with capture:
d["key2"] = "value2"
m.print_dict(d)
- assert capture.unordered == """
+ assert (
+ capture.unordered
+ == """
key: key, value=value
key: key2, value=value2
"""
+ )
assert not m.dict_contains({}, 42)
assert m.dict_contains({42: None}, 42)
@@ -84,18 +113,30 @@ def test_str(doc):
assert m.str_from_object(A()) == "this is a str"
assert m.repr_from_object(A()) == "this is a repr"
+ assert m.str_from_handle(A()) == "this is a str"
s1, s2 = m.str_format()
assert s1 == "1 + 2 = 3"
assert s1 == s2
+ malformed_utf8 = b"\x80"
+ assert m.str_from_object(malformed_utf8) is malformed_utf8 # To be fixed; see #2380
+ if env.PY2:
+ # with pytest.raises(UnicodeDecodeError):
+ # m.str_from_object(malformed_utf8)
+ with pytest.raises(UnicodeDecodeError):
+ m.str_from_handle(malformed_utf8)
+ else:
+ # assert m.str_from_object(malformed_utf8) == "b'\\x80'"
+ assert m.str_from_handle(malformed_utf8) == "b'\\x80'"
+
def test_bytes(doc):
assert m.bytes_from_string().decode() == "foo"
assert m.bytes_from_str().decode() == "bar"
assert doc(m.bytes_from_str) == "bytes_from_str() -> {}".format(
- "bytes" if sys.version_info[0] == 3 else "str"
+ "str" if env.PY2 else "bytes"
)
@@ -105,28 +146,37 @@ def test_capsule(capture):
a = m.return_capsule_with_destructor()
del a
pytest.gc_collect()
- assert capture.unordered == """
+ assert (
+ capture.unordered
+ == """
creating capsule
destructing capsule
"""
+ )
with capture:
a = m.return_capsule_with_destructor_2()
del a
pytest.gc_collect()
- assert capture.unordered == """
+ assert (
+ capture.unordered
+ == """
creating capsule
destructing capsule: 1234
"""
+ )
with capture:
a = m.return_capsule_with_name_and_destructor()
del a
pytest.gc_collect()
- assert capture.unordered == """
+ assert (
+ capture.unordered
+ == """
created capsule (1234, 'pointer type description')
destructing capsule (1234, 'pointer type description')
"""
+ )
def test_accessors():
@@ -170,11 +220,17 @@ def test_accessors():
def test_constructors():
"""C++ default and converting constructors are equivalent to type calls in Python"""
- types = [str, bool, int, float, tuple, list, dict, set]
+ types = [bytes, str, bool, int, float, tuple, list, dict, set]
expected = {t.__name__: t() for t in types}
+ if env.PY2:
+ # Note that bytes.__name__ == 'str' in Python 2.
+ # pybind11::str is unicode even under Python 2.
+ expected["bytes"] = bytes()
+ expected["str"] = unicode() # noqa: F821
assert m.default_constructors() == expected
data = {
+ bytes: b"41", # Currently no supported or working conversions.
str: 42,
bool: "Not empty",
int: "42",
@@ -183,10 +239,15 @@ def test_constructors():
list: range(3),
dict: [("two", 2), ("one", 1), ("three", 3)],
set: [4, 4, 5, 6, 6, 6],
- memoryview: b'abc'
+ memoryview: b"abc",
}
inputs = {k.__name__: v for k, v in data.items()}
expected = {k.__name__: k(v) for k, v in data.items()}
+ if env.PY2: # Similar to the above. See comments above.
+ inputs["bytes"] = b"41"
+ inputs["str"] = 42
+ expected["bytes"] = b"41"
+ expected["str"] = u"42"
assert m.converting_constructors(inputs) == expected
assert m.cast_functions(inputs) == expected
@@ -202,21 +263,79 @@ def test_constructors():
assert noconv2[k] is expected[k]
+def test_non_converting_constructors():
+ non_converting_test_cases = [
+ ("bytes", range(10)),
+ ("none", 42),
+ ("ellipsis", 42),
+ ]
+ for t, v in non_converting_test_cases:
+ with pytest.raises(TypeError) as excinfo:
+ m.nonconverting_constructor(t, v)
+ expected_error = "Object of type '{}' is not an instance of '{}'".format(
+ type(v).__name__, t
+ )
+ assert str(excinfo.value) == expected_error
+
+
+def test_pybind11_str_raw_str():
+ # specifically to exercise pybind11::str::raw_str
+ cvt = m.convert_to_pybind11_str
+ assert cvt(u"Str") == u"Str"
+ assert cvt(b"Bytes") == u"Bytes" if env.PY2 else "b'Bytes'"
+ assert cvt(None) == u"None"
+ assert cvt(False) == u"False"
+ assert cvt(True) == u"True"
+ assert cvt(42) == u"42"
+ assert cvt(2 ** 65) == u"36893488147419103232"
+ assert cvt(-1.50) == u"-1.5"
+ assert cvt(()) == u"()"
+ assert cvt((18,)) == u"(18,)"
+ assert cvt([]) == u"[]"
+ assert cvt([28]) == u"[28]"
+ assert cvt({}) == u"{}"
+ assert cvt({3: 4}) == u"{3: 4}"
+ assert cvt(set()) == u"set([])" if env.PY2 else "set()"
+ assert cvt({3, 3}) == u"set([3])" if env.PY2 else "{3}"
+
+ valid_orig = u"DZ"
+ valid_utf8 = valid_orig.encode("utf-8")
+ valid_cvt = cvt(valid_utf8)
+ assert type(valid_cvt) == bytes # Probably surprising.
+ assert valid_cvt == b"\xc7\xb1"
+
+ malformed_utf8 = b"\x80"
+ malformed_cvt = cvt(malformed_utf8)
+ assert type(malformed_cvt) == bytes # Probably surprising.
+ assert malformed_cvt == b"\x80"
+
+
def test_implicit_casting():
"""Tests implicit casting when assigning or appending to dicts and lists."""
z = m.get_implicit_casting()
- assert z['d'] == {
- 'char*_i1': 'abc', 'char*_i2': 'abc', 'char*_e': 'abc', 'char*_p': 'abc',
- 'str_i1': 'str', 'str_i2': 'str1', 'str_e': 'str2', 'str_p': 'str3',
- 'int_i1': 42, 'int_i2': 42, 'int_e': 43, 'int_p': 44
+ assert z["d"] == {
+ "char*_i1": "abc",
+ "char*_i2": "abc",
+ "char*_e": "abc",
+ "char*_p": "abc",
+ "str_i1": "str",
+ "str_i2": "str1",
+ "str_e": "str2",
+ "str_p": "str3",
+ "int_i1": 42,
+ "int_i2": 42,
+ "int_e": 43,
+ "int_p": 44,
}
- assert z['l'] == [3, 6, 9, 12, 15]
+ assert z["l"] == [3, 6, 9, 12, 15]
def test_print(capture):
with capture:
m.print_function()
- assert capture == """
+ assert (
+ capture
+ == """
Hello, World!
1 2.0 three True -- multiple args
*args-and-a-custom-separator
@@ -224,14 +343,15 @@ def test_print(capture):
flush
py::print + str.format = this
"""
+ )
assert capture.stderr == "this goes to stderr"
with pytest.raises(RuntimeError) as excinfo:
m.print_failure()
assert str(excinfo.value) == "make_tuple(): unable to convert " + (
"argument of type 'UnregisteredType' to Python object"
- if debug_enabled else
- "arguments to Python object (compile in debug mode for details)"
+ if debug_enabled
+ else "arguments to Python object (compile in debug mode for details)"
)
@@ -253,11 +373,116 @@ def test_hash():
def test_number_protocol():
for a, b in [(1, 1), (3, 5)]:
- li = [a == b, a != b, a < b, a <= b, a > b, a >= b, a + b,
- a - b, a * b, a / b, a | b, a & b, a ^ b, a >> b, a << b]
+ li = [
+ a == b,
+ a != b,
+ a < b,
+ a <= b,
+ a > b,
+ a >= b,
+ a + b,
+ a - b,
+ a * b,
+ a / b,
+ a | b,
+ a & b,
+ a ^ b,
+ a >> b,
+ a << b,
+ ]
assert m.test_number_protocol(a, b) == li
def test_list_slicing():
li = list(range(100))
assert li[::2] == m.test_list_slicing(li)
+
+
+def test_issue2361():
+ # See issue #2361
+ assert m.issue2361_str_implicit_copy_none() == "None"
+ with pytest.raises(TypeError) as excinfo:
+ assert m.issue2361_dict_implicit_copy_none()
+ assert "'NoneType' object is not iterable" in str(excinfo.value)
+
+
+@pytest.mark.parametrize(
+ "method, args, fmt, expected_view",
+ [
+ (m.test_memoryview_object, (b"red",), "B", b"red"),
+ (m.test_memoryview_buffer_info, (b"green",), "B", b"green"),
+ (m.test_memoryview_from_buffer, (False,), "h", [3, 1, 4, 1, 5]),
+ (m.test_memoryview_from_buffer, (True,), "H", [2, 7, 1, 8]),
+ (m.test_memoryview_from_buffer_nativeformat, (), "@i", [4, 7, 5]),
+ ],
+)
+def test_memoryview(method, args, fmt, expected_view):
+ view = method(*args)
+ assert isinstance(view, memoryview)
+ assert view.format == fmt
+ if isinstance(expected_view, bytes) or not env.PY2:
+ view_as_list = list(view)
+ else:
+ # Using max to pick non-zero byte (big-endian vs little-endian).
+ view_as_list = [max([ord(c) for c in s]) for s in view]
+ assert view_as_list == list(expected_view)
+
+
+@pytest.mark.xfail("env.PYPY", reason="getrefcount is not available")
+@pytest.mark.parametrize(
+ "method",
+ [
+ m.test_memoryview_object,
+ m.test_memoryview_buffer_info,
+ ],
+)
+def test_memoryview_refcount(method):
+ buf = b"\x0a\x0b\x0c\x0d"
+ ref_before = sys.getrefcount(buf)
+ view = method(buf)
+ ref_after = sys.getrefcount(buf)
+ assert ref_before < ref_after
+ assert list(view) == list(buf)
+
+
+def test_memoryview_from_buffer_empty_shape():
+ view = m.test_memoryview_from_buffer_empty_shape()
+ assert isinstance(view, memoryview)
+ assert view.format == "B"
+ if env.PY2:
+ # Python 2 behavior is weird, but Python 3 (the future) is fine.
+ # PyPy3 has <memoryview, while CPython 2 has <memory
+ assert bytes(view).startswith(b"<memory")
+ else:
+ assert bytes(view) == b""
+
+
+def test_test_memoryview_from_buffer_invalid_strides():
+ with pytest.raises(RuntimeError):
+ m.test_memoryview_from_buffer_invalid_strides()
+
+
+def test_test_memoryview_from_buffer_nullptr():
+ if env.PY2:
+ m.test_memoryview_from_buffer_nullptr()
+ else:
+ with pytest.raises(ValueError):
+ m.test_memoryview_from_buffer_nullptr()
+
+
+@pytest.mark.skipif("env.PY2")
+def test_memoryview_from_memory():
+ view = m.test_memoryview_from_memory()
+ assert isinstance(view, memoryview)
+ assert view.format == "B"
+ assert bytes(view) == b"\xff\xe1\xab\x37"
+
+
+def test_builtin_functions():
+ assert m.get_len([i for i in range(42)]) == 42
+ with pytest.raises(TypeError) as exc_info:
+ m.get_len(i for i in range(42))
+ assert str(exc_info.value) in [
+ "object of type 'generator' has no len()",
+ "'generator' has no length",
+ ] # PyPy
diff --git a/3rdparty/pybind11/tests/test_sequences_and_iterators.cpp b/3rdparty/pybind11/tests/test_sequences_and_iterators.cpp
index 87ccf99d..d318052a 100644
--- a/3rdparty/pybind11/tests/test_sequences_and_iterators.cpp
+++ b/3rdparty/pybind11/tests/test_sequences_and_iterators.cpp
@@ -13,6 +13,8 @@
#include <pybind11/operators.h>
#include <pybind11/stl.h>
+#include <algorithm>
+
template<typename T>
class NonZeroIterator {
const T* ptr_;
@@ -81,7 +83,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
py::class_<Sliceable>(m,"Sliceable")
.def(py::init<int>())
.def("__getitem__",[](const Sliceable &s, py::slice slice) {
- ssize_t start, stop, step, slicelength;
+ py::ssize_t start, stop, step, slicelength;
if (!slice.compute(s.size, &start, &stop, &step, &slicelength))
throw py::error_already_set();
int istart = static_cast<int>(start);
@@ -198,7 +200,7 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
size_t start, stop, step, slicelength;
if (!slice.compute(s.size(), &start, &stop, &step, &slicelength))
throw py::error_already_set();
- Sequence *seq = new Sequence(slicelength);
+ auto *seq = new Sequence(slicelength);
for (size_t i = 0; i < slicelength; ++i) {
(*seq)[i] = s[start]; start += step;
}
@@ -319,6 +321,9 @@ TEST_SUBMODULE(sequences_and_iterators, m) {
return l;
});
+ // test_sequence_length: check that Python sequences can be converted to py::sequence.
+ m.def("sequence_length", [](py::sequence seq) { return seq.size(); });
+
// Make sure that py::iterator works with std algorithms
m.def("count_none", [](py::object o) {
return std::count_if(o.begin(), o.end(), [](py::handle h) { return h.is_none(); });
diff --git a/3rdparty/pybind11/tests/test_sequences_and_iterators.py b/3rdparty/pybind11/tests/test_sequences_and_iterators.py
index 6bd16064..c3b608c4 100644
--- a/3rdparty/pybind11/tests/test_sequences_and_iterators.py
+++ b/3rdparty/pybind11/tests/test_sequences_and_iterators.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import sequences_and_iterators as m
from pybind11_tests import ConstructorStats
@@ -9,7 +10,9 @@ def isclose(a, b, rel_tol=1e-05, abs_tol=0.0):
def allclose(a_list, b_list, rel_tol=1e-05, abs_tol=0.0):
- return all(isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) for a, b in zip(a_list, b_list))
+ return all(
+ isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol) for a, b in zip(a_list, b_list)
+ )
def test_generalized_iterators():
@@ -50,7 +53,7 @@ def test_sequence():
cstats = ConstructorStats.get(m.Sequence)
s = m.Sequence(5)
- assert cstats.values() == ['of size', '5']
+ assert cstats.values() == ["of size", "5"]
assert "Sequence" in repr(s)
assert len(s) == 5
@@ -61,16 +64,16 @@ def test_sequence():
assert isclose(s[0], 12.34) and isclose(s[3], 56.78)
rev = reversed(s)
- assert cstats.values() == ['of size', '5']
+ assert cstats.values() == ["of size", "5"]
rev2 = s[::-1]
- assert cstats.values() == ['of size', '5']
+ assert cstats.values() == ["of size", "5"]
it = iter(m.Sequence(0))
for _ in range(3): # __next__ must continue to raise StopIteration
with pytest.raises(StopIteration):
next(it)
- assert cstats.values() == ['of size', '0']
+ assert cstats.values() == ["of size", "0"]
expected = [0, 56.78, 0, 0, 12.34]
assert allclose(rev, expected)
@@ -78,7 +81,7 @@ def test_sequence():
assert rev == rev2
rev[0::2] = m.Sequence([2.0, 2.0, 2.0])
- assert cstats.values() == ['of size', '3', 'from std::vector']
+ assert cstats.values() == ["of size", "3", "from std::vector"]
assert allclose(rev, [2, 56.78, 2, 0, 2])
@@ -100,18 +103,38 @@ def test_sequence():
assert cstats.move_assignments == 0
+def test_sequence_length():
+ """#2076: Exception raised by len(arg) should be propagated """
+
+ class BadLen(RuntimeError):
+ pass
+
+ class SequenceLike:
+ def __getitem__(self, i):
+ return None
+
+ def __len__(self):
+ raise BadLen()
+
+ with pytest.raises(BadLen):
+ m.sequence_length(SequenceLike())
+
+ assert m.sequence_length([1, 2, 3]) == 3
+ assert m.sequence_length("hello") == 5
+
+
def test_map_iterator():
- sm = m.StringMap({'hi': 'bye', 'black': 'white'})
- assert sm['hi'] == 'bye'
+ sm = m.StringMap({"hi": "bye", "black": "white"})
+ assert sm["hi"] == "bye"
assert len(sm) == 2
- assert sm['black'] == 'white'
+ assert sm["black"] == "white"
with pytest.raises(KeyError):
- assert sm['orange']
- sm['orange'] = 'banana'
- assert sm['orange'] == 'banana'
+ assert sm["orange"]
+ sm["orange"] = "banana"
+ assert sm["orange"] == "banana"
- expected = {'hi': 'bye', 'black': 'white', 'orange': 'banana'}
+ expected = {"hi": "bye", "black": "white", "orange": "banana"}
for k in sm:
assert sm[k] == expected[k]
for k, v in sm.items():
@@ -159,7 +182,8 @@ def test_iterator_passthrough():
"""#181: iterator passthrough did not compile"""
from pybind11_tests.sequences_and_iterators import iterator_passthrough
- assert list(iterator_passthrough(iter([3, 5, 7, 9, 11, 13, 15]))) == [3, 5, 7, 9, 11, 13, 15]
+ values = [3, 5, 7, 9, 11, 13, 15]
+ assert list(iterator_passthrough(iter(values))) == values
def test_iterator_rvp():
diff --git a/3rdparty/pybind11/tests/test_smart_ptr.cpp b/3rdparty/pybind11/tests/test_smart_ptr.cpp
index 87c9be8c..60c2e692 100644
--- a/3rdparty/pybind11/tests/test_smart_ptr.cpp
+++ b/3rdparty/pybind11/tests/test_smart_ptr.cpp
@@ -27,7 +27,8 @@ namespace pybind11 { namespace detail {
struct holder_helper<ref<T>> {
static const T *get(const ref<T> &p) { return p.get_ptr(); }
};
-}}
+} // namespace detail
+} // namespace pybind11
// The following is not required anymore for std::shared_ptr, but it should compile without error:
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);
@@ -97,9 +98,9 @@ TEST_SUBMODULE(smart_ptr, m) {
class MyObject1 : public Object {
public:
MyObject1(int value) : value(value) { print_created(this, toString()); }
- std::string toString() const { return "MyObject1[" + std::to_string(value) + "]"; }
+ std::string toString() const override { return "MyObject1[" + std::to_string(value) + "]"; }
protected:
- virtual ~MyObject1() { print_destroyed(this); }
+ ~MyObject1() override { print_destroyed(this); }
private:
int value;
};
@@ -207,7 +208,7 @@ TEST_SUBMODULE(smart_ptr, m) {
class MyObject4b : public MyObject4a {
public:
MyObject4b(int i) : MyObject4a(i) { print_created(this); }
- ~MyObject4b() { print_destroyed(this); }
+ ~MyObject4b() override { print_destroyed(this); }
};
py::class_<MyObject4b, MyObject4a>(m, "MyObject4b")
.def(py::init<int>());
@@ -291,7 +292,8 @@ TEST_SUBMODULE(smart_ptr, m) {
~C() { print_destroyed(this); }
};
py::class_<C, custom_unique_ptr<C>>(m, "TypeWithMoveOnlyHolder")
- .def_static("make", []() { return custom_unique_ptr<C>(new C); });
+ .def_static("make", []() { return custom_unique_ptr<C>(new C); })
+ .def_static("make_as_object", []() { return py::cast(custom_unique_ptr<C>(new C)); });
// test_holder_with_addressof_operator
struct TypeForHolderWithAddressOf {
@@ -337,7 +339,9 @@ TEST_SUBMODULE(smart_ptr, m) {
// test_shared_ptr_gc
// #187: issue involving std::shared_ptr<> return value policy & garbage collection
struct ElementBase {
- virtual ~ElementBase() { } /* Force creation of virtual table */
+ virtual ~ElementBase() = default; /* Force creation of virtual table */
+ ElementBase() = default;
+ ElementBase(const ElementBase&) = delete;
};
py::class_<ElementBase, std::shared_ptr<ElementBase>>(m, "ElementBase");
diff --git a/3rdparty/pybind11/tests/test_smart_ptr.py b/3rdparty/pybind11/tests/test_smart_ptr.py
index c6627043..c55bffba 100644
--- a/3rdparty/pybind11/tests/test_smart_ptr.py
+++ b/3rdparty/pybind11/tests/test_smart_ptr.py
@@ -1,11 +1,15 @@
+# -*- coding: utf-8 -*-
import pytest
-from pybind11_tests import smart_ptr as m
-from pybind11_tests import ConstructorStats
+
+m = pytest.importorskip("pybind11_tests.smart_ptr")
+from pybind11_tests import ConstructorStats # noqa: E402
def test_smart_ptr(capture):
# Object1
- for i, o in enumerate([m.make_object_1(), m.make_object_2(), m.MyObject1(3)], start=1):
+ for i, o in enumerate(
+ [m.make_object_1(), m.make_object_2(), m.MyObject1(3)], start=1
+ ):
assert o.getRefCount() == 1
with capture:
m.print_object_1(o)
@@ -14,8 +18,9 @@ def test_smart_ptr(capture):
m.print_object_4(o)
assert capture == "MyObject1[{i}]\n".format(i=i) * 4
- for i, o in enumerate([m.make_myobject1_1(), m.make_myobject1_2(), m.MyObject1(6), 7],
- start=4):
+ for i, o in enumerate(
+ [m.make_myobject1_1(), m.make_myobject1_2(), m.MyObject1(6), 7], start=4
+ ):
print(o)
with capture:
if not isinstance(o, int):
@@ -27,11 +32,15 @@ def test_smart_ptr(capture):
m.print_myobject1_2(o)
m.print_myobject1_3(o)
m.print_myobject1_4(o)
- assert capture == "MyObject1[{i}]\n".format(i=i) * (4 if isinstance(o, int) else 8)
+
+ times = 4 if isinstance(o, int) else 8
+ assert capture == "MyObject1[{i}]\n".format(i=i) * times
cstats = ConstructorStats.get(m.MyObject1)
assert cstats.alive() == 0
- expected_values = ['MyObject1[{}]'.format(i) for i in range(1, 7)] + ['MyObject1[7]'] * 4
+ expected_values = ["MyObject1[{}]".format(i) for i in range(1, 7)] + [
+ "MyObject1[7]"
+ ] * 4
assert cstats.values() == expected_values
assert cstats.default_constructions == 0
assert cstats.copy_constructions == 0
@@ -40,7 +49,9 @@ def test_smart_ptr(capture):
assert cstats.move_assignments == 0
# Object2
- for i, o in zip([8, 6, 7], [m.MyObject2(8), m.make_myobject2_1(), m.make_myobject2_2()]):
+ for i, o in zip(
+ [8, 6, 7], [m.MyObject2(8), m.make_myobject2_1(), m.make_myobject2_2()]
+ ):
print(o)
with capture:
m.print_myobject2_1(o)
@@ -53,7 +64,7 @@ def test_smart_ptr(capture):
assert cstats.alive() == 1
o = None
assert cstats.alive() == 0
- assert cstats.values() == ['MyObject2[8]', 'MyObject2[6]', 'MyObject2[7]']
+ assert cstats.values() == ["MyObject2[8]", "MyObject2[6]", "MyObject2[7]"]
assert cstats.default_constructions == 0
assert cstats.copy_constructions == 0
# assert cstats.move_constructions >= 0 # Doesn't invoke any
@@ -61,7 +72,9 @@ def test_smart_ptr(capture):
assert cstats.move_assignments == 0
# Object3
- for i, o in zip([9, 8, 9], [m.MyObject3(9), m.make_myobject3_1(), m.make_myobject3_2()]):
+ for i, o in zip(
+ [9, 8, 9], [m.MyObject3(9), m.make_myobject3_1(), m.make_myobject3_2()]
+ ):
print(o)
with capture:
m.print_myobject3_1(o)
@@ -74,7 +87,7 @@ def test_smart_ptr(capture):
assert cstats.alive() == 1
o = None
assert cstats.alive() == 0
- assert cstats.values() == ['MyObject3[9]', 'MyObject3[8]', 'MyObject3[9]']
+ assert cstats.values() == ["MyObject3[9]", "MyObject3[8]", "MyObject3[9]"]
assert cstats.default_constructions == 0
assert cstats.copy_constructions == 0
# assert cstats.move_constructions >= 0 # Doesn't invoke any
@@ -94,7 +107,7 @@ def test_smart_ptr(capture):
# ref<>
cstats = m.cstats_ref()
assert cstats.alive() == 0
- assert cstats.values() == ['from pointer'] * 10
+ assert cstats.values() == ["from pointer"] * 10
assert cstats.default_constructions == 30
assert cstats.copy_constructions == 12
# assert cstats.move_constructions >= 0 # Doesn't invoke any
@@ -184,7 +197,9 @@ def test_shared_ptr_from_this_and_references():
ref = s.ref # init_holder_helper(holder_ptr=false, owned=false, bad_wp=false)
assert stats.alive() == 2
assert s.set_ref(ref)
- assert s.set_holder(ref) # std::enable_shared_from_this can create a holder from a reference
+ assert s.set_holder(
+ ref
+ ) # std::enable_shared_from_this can create a holder from a reference
bad_wp = s.bad_wp # init_holder_helper(holder_ptr=false, owned=false, bad_wp=true)
assert stats.alive() == 2
@@ -198,12 +213,16 @@ def test_shared_ptr_from_this_and_references():
assert s.set_ref(copy)
assert s.set_holder(copy)
- holder_ref = s.holder_ref # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false)
+ holder_ref = (
+ s.holder_ref
+ ) # init_holder_helper(holder_ptr=true, owned=false, bad_wp=false)
assert stats.alive() == 3
assert s.set_ref(holder_ref)
assert s.set_holder(holder_ref)
- holder_copy = s.holder_copy # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false)
+ holder_copy = (
+ s.holder_copy
+ ) # init_holder_helper(holder_ptr=true, owned=true, bad_wp=false)
assert stats.alive() == 3
assert s.set_ref(holder_copy)
assert s.set_holder(holder_copy)
@@ -218,7 +237,10 @@ def test_shared_ptr_from_this_and_references():
def test_move_only_holder():
a = m.TypeWithMoveOnlyHolder.make()
+ b = m.TypeWithMoveOnlyHolder.make_as_object()
stats = ConstructorStats.get(m.TypeWithMoveOnlyHolder)
+ assert stats.alive() == 2
+ del b
assert stats.alive() == 1
del a
assert stats.alive() == 0
@@ -272,8 +294,10 @@ def test_smart_ptr_from_default():
instance = m.HeldByDefaultHolder()
with pytest.raises(RuntimeError) as excinfo:
m.HeldByDefaultHolder.load_shared_ptr(instance)
- assert "Unable to load a custom holder type from a " \
- "default-holder instance" in str(excinfo.value)
+ assert (
+ "Unable to load a custom holder type from a "
+ "default-holder instance" in str(excinfo.value)
+ )
def test_shared_ptr_gc():
diff --git a/3rdparty/pybind11/tests/test_stl.cpp b/3rdparty/pybind11/tests/test_stl.cpp
index 207c9fb2..05901627 100644
--- a/3rdparty/pybind11/tests/test_stl.cpp
+++ b/3rdparty/pybind11/tests/test_stl.cpp
@@ -15,7 +15,7 @@
#include <string>
// Test with `std::variant` in C++17 mode, or with `boost::variant` in C++11/14
-#if PYBIND11_HAS_VARIANT
+#if defined(PYBIND11_HAS_VARIANT)
using std::variant;
#elif defined(PYBIND11_TEST_BOOST) && (!defined(_MSC_VER) || _MSC_VER >= 1910)
# include <boost/variant.hpp>
@@ -47,7 +47,18 @@ struct TplCtorClass {
namespace std {
template <>
struct hash<TplCtorClass> { size_t operator()(const TplCtorClass &) const { return 0; } };
-}
+} // namespace std
+
+
+template <template <typename> class OptionalImpl, typename T>
+struct OptionalHolder
+{
+ OptionalHolder() = default;
+ bool member_initialized() const {
+ return member && member->initialized;
+ }
+ OptionalImpl<T> member = T{};
+};
TEST_SUBMODULE(stl, m) {
@@ -154,6 +165,23 @@ TEST_SUBMODULE(stl, m) {
.def(py::init<>())
.def(py::init<int>());
+
+ struct MoveOutDetector
+ {
+ MoveOutDetector() = default;
+ MoveOutDetector(const MoveOutDetector&) = default;
+ MoveOutDetector(MoveOutDetector&& other) noexcept
+ : initialized(other.initialized) {
+ // steal underlying resource
+ other.initialized = false;
+ }
+ bool initialized = true;
+ };
+ py::class_<MoveOutDetector>(m, "MoveOutDetector", "Class with move tracking")
+ .def(py::init<>())
+ .def_readonly("initialized", &MoveOutDetector::initialized);
+
+
#ifdef PYBIND11_HAS_OPTIONAL
// test_optional
m.attr("has_optional") = true;
@@ -175,6 +203,12 @@ TEST_SUBMODULE(stl, m) {
m.def("nodefer_none_optional", [](std::optional<int>) { return true; });
m.def("nodefer_none_optional", [](py::none) { return false; });
+
+ using opt_holder = OptionalHolder<std::optional, MoveOutDetector>;
+ py::class_<opt_holder>(m, "OptionalHolder", "Class with optional member")
+ .def(py::init<>())
+ .def_readonly("member", &opt_holder::member)
+ .def("member_initialized", &opt_holder::member_initialized);
#endif
#ifdef PYBIND11_HAS_EXP_OPTIONAL
@@ -195,6 +229,12 @@ TEST_SUBMODULE(stl, m) {
m.def("test_no_assign_exp", [](const exp_opt_no_assign &x) {
return x ? x->value : 42;
}, py::arg_v("x", std::experimental::nullopt, "None"));
+
+ using opt_exp_holder = OptionalHolder<std::experimental::optional, MoveOutDetector>;
+ py::class_<opt_exp_holder>(m, "OptionalExpHolder", "Class with optional member")
+ .def(py::init<>())
+ .def_readonly("member", &opt_exp_holder::member)
+ .def("member_initialized", &opt_exp_holder::member_initialized);
#endif
#ifdef PYBIND11_HAS_VARIANT
diff --git a/3rdparty/pybind11/tests/test_stl.py b/3rdparty/pybind11/tests/test_stl.py
index 2335cb9f..33001754 100644
--- a/3rdparty/pybind11/tests/test_stl.py
+++ b/3rdparty/pybind11/tests/test_stl.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import stl as m
@@ -87,7 +88,7 @@ def test_recursive_casting():
assert m.cast_rv_nested() == [[[{"b": "rvalue", "c": "rvalue"}], [{"a": "rvalue"}]]]
assert m.cast_lv_nested() == {
"a": [[["lvalue", "lvalue"]], [["lvalue", "lvalue"]]],
- "b": [[["lvalue", "lvalue"], ["lvalue", "lvalue"]]]
+ "b": [[["lvalue", "lvalue"], ["lvalue", "lvalue"]]],
}
# Issue #853 test case:
@@ -105,15 +106,15 @@ def test_move_out_container():
assert [x.value for x in moved_out_list] == [0, 1, 2]
-@pytest.mark.skipif(not hasattr(m, "has_optional"), reason='no <optional>')
+@pytest.mark.skipif(not hasattr(m, "has_optional"), reason="no <optional>")
def test_optional():
assert m.double_or_zero(None) == 0
assert m.double_or_zero(42) == 84
- pytest.raises(TypeError, m.double_or_zero, 'foo')
+ pytest.raises(TypeError, m.double_or_zero, "foo")
assert m.half_or_none(0) is None
assert m.half_or_none(42) == 21
- pytest.raises(TypeError, m.half_or_none, 'foo')
+ pytest.raises(TypeError, m.half_or_none, "foo")
assert m.test_nullopt() == 42
assert m.test_nullopt(None) == 42
@@ -127,16 +128,23 @@ def test_optional():
assert m.nodefer_none_optional(None)
+ holder = m.OptionalHolder()
+ mvalue = holder.member
+ assert mvalue.initialized
+ assert holder.member_initialized()
-@pytest.mark.skipif(not hasattr(m, "has_exp_optional"), reason='no <experimental/optional>')
+
+@pytest.mark.skipif(
+ not hasattr(m, "has_exp_optional"), reason="no <experimental/optional>"
+)
def test_exp_optional():
assert m.double_or_zero_exp(None) == 0
assert m.double_or_zero_exp(42) == 84
- pytest.raises(TypeError, m.double_or_zero_exp, 'foo')
+ pytest.raises(TypeError, m.double_or_zero_exp, "foo")
assert m.half_or_none_exp(0) is None
assert m.half_or_none_exp(42) == 21
- pytest.raises(TypeError, m.half_or_none_exp, 'foo')
+ pytest.raises(TypeError, m.half_or_none_exp, "foo")
assert m.test_nullopt_exp() == 42
assert m.test_nullopt_exp(None) == 42
@@ -148,8 +156,13 @@ def test_exp_optional():
assert m.test_no_assign_exp(m.NoAssign(43)) == 43
pytest.raises(TypeError, m.test_no_assign_exp, 43)
+ holder = m.OptionalExpHolder()
+ mvalue = holder.member
+ assert mvalue.initialized
+ assert holder.member_initialized()
+
-@pytest.mark.skipif(not hasattr(m, "load_variant"), reason='no <variant>')
+@pytest.mark.skipif(not hasattr(m, "load_variant"), reason="no <variant>")
def test_variant(doc):
assert m.load_variant(1) == "int"
assert m.load_variant("1") == "std::string"
@@ -161,34 +174,44 @@ def test_variant(doc):
assert m.cast_variant() == (5, "Hello")
- assert doc(m.load_variant) == "load_variant(arg0: Union[int, str, float, None]) -> str"
+ assert (
+ doc(m.load_variant) == "load_variant(arg0: Union[int, str, float, None]) -> str"
+ )
def test_vec_of_reference_wrapper():
"""#171: Can't return reference wrappers (or STL structures containing them)"""
- assert str(m.return_vec_of_reference_wrapper(UserType(4))) == \
- "[UserType(1), UserType(2), UserType(3), UserType(4)]"
+ assert (
+ str(m.return_vec_of_reference_wrapper(UserType(4)))
+ == "[UserType(1), UserType(2), UserType(3), UserType(4)]"
+ )
def test_stl_pass_by_pointer(msg):
"""Passing nullptr or None to an STL container pointer is not expected to work"""
with pytest.raises(TypeError) as excinfo:
m.stl_pass_by_pointer() # default value is `nullptr`
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
stl_pass_by_pointer(): incompatible function arguments. The following argument types are supported:
1. (v: List[int] = None) -> List[int]
Invoked with:
""" # noqa: E501 line too long
+ )
with pytest.raises(TypeError) as excinfo:
m.stl_pass_by_pointer(None)
- assert msg(excinfo.value) == """
+ assert (
+ msg(excinfo.value)
+ == """
stl_pass_by_pointer(): incompatible function arguments. The following argument types are supported:
1. (v: List[int] = None) -> List[int]
Invoked with: None
""" # noqa: E501 line too long
+ )
assert m.stl_pass_by_pointer([1, 2, 3]) == [1, 2, 3]
@@ -198,10 +221,12 @@ def test_missing_header_message():
<pybind11/stl.h> should result in a helpful suggestion in the error message"""
import pybind11_cross_module_tests as cm
- expected_message = ("Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,\n"
- "<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic\n"
- "conversions are optional and require extra headers to be included\n"
- "when compiling your pybind11 module.")
+ expected_message = (
+ "Did you forget to `#include <pybind11/stl.h>`? Or <pybind11/complex.h>,\n"
+ "<pybind11/functional.h>, <pybind11/chrono.h>, etc. Some automatic\n"
+ "conversions are optional and require extra headers to be included\n"
+ "when compiling your pybind11 module."
+ )
with pytest.raises(TypeError) as excinfo:
cm.missing_header_arg([1.0, 2.0, 3.0])
@@ -215,9 +240,9 @@ def test_missing_header_message():
def test_function_with_string_and_vector_string_arg():
"""Check if a string is NOT implicitly converted to a list, which was the
behavior before fix of issue #1258"""
- assert m.func_with_string_or_vector_string_arg_overload(('A', 'B', )) == 2
- assert m.func_with_string_or_vector_string_arg_overload(['A', 'B']) == 2
- assert m.func_with_string_or_vector_string_arg_overload('A') == 3
+ assert m.func_with_string_or_vector_string_arg_overload(("A", "B")) == 2
+ assert m.func_with_string_or_vector_string_arg_overload(["A", "B"]) == 2
+ assert m.func_with_string_or_vector_string_arg_overload("A") == 3
def test_stl_ownership():
@@ -236,6 +261,6 @@ def test_array_cast_sequence():
def test_issue_1561():
""" check fix for issue #1561 """
bar = m.Issue1561Outer()
- bar.list = [m.Issue1561Inner('bar')]
+ bar.list = [m.Issue1561Inner("bar")]
bar.list
- assert bar.list[0].data == 'bar'
+ assert bar.list[0].data == "bar"
diff --git a/3rdparty/pybind11/tests/test_stl_binders.cpp b/3rdparty/pybind11/tests/test_stl_binders.cpp
index 86888740..1c0df984 100644
--- a/3rdparty/pybind11/tests/test_stl_binders.cpp
+++ b/3rdparty/pybind11/tests/test_stl_binders.cpp
@@ -117,7 +117,7 @@ TEST_SUBMODULE(stl_binders, m) {
});
// The rest depends on numpy:
- try { py::module::import("numpy"); }
+ try { py::module_::import("numpy"); }
catch (...) { return; }
// test_vector_buffer_numpy
diff --git a/3rdparty/pybind11/tests/test_stl_binders.py b/3rdparty/pybind11/tests/test_stl_binders.py
index c7b7e853..84132a2b 100644
--- a/3rdparty/pybind11/tests/test_stl_binders.py
+++ b/3rdparty/pybind11/tests/test_stl_binders.py
@@ -1,9 +1,9 @@
+# -*- coding: utf-8 -*-
import pytest
-import sys
-from pybind11_tests import stl_binders as m
-with pytest.suppress(ImportError):
- import numpy as np
+import env # noqa: F401
+
+from pybind11_tests import stl_binders as m
def test_vector_int():
@@ -45,7 +45,7 @@ def test_vector_int():
# test error handling, and that the vector is unchanged
with pytest.raises(RuntimeError):
- v_int2.extend([8, 'a'])
+ v_int2.extend([8, "a"])
assert v_int2 == m.VectorInt([0, 99, 2, 3, 4, 5, 6, 7])
@@ -67,30 +67,34 @@ def test_vector_int():
v_int2.clear()
assert len(v_int2) == 0
-# related to the PyPy's buffer protocol.
-@pytest.unsupported_on_pypy
+
+# Older PyPy's failed here, related to the PyPy's buffer protocol.
def test_vector_buffer():
b = bytearray([1, 2, 3, 4])
v = m.VectorUChar(b)
assert v[1] == 2
v[2] = 5
mv = memoryview(v) # We expose the buffer interface
- if sys.version_info.major > 2:
+ if not env.PY2:
assert mv[2] == 5
mv[2] = 6
else:
- assert mv[2] == '\x05'
- mv[2] = '\x06'
+ assert mv[2] == "\x05"
+ mv[2] = "\x06"
assert v[2] == 6
+ if not env.PY2:
+ mv = memoryview(b)
+ v = m.VectorUChar(mv[::2])
+ assert v[1] == 3
+
with pytest.raises(RuntimeError) as excinfo:
m.create_undeclstruct() # Undeclared struct contents, no buffer interface
assert "NumPy type info missing for " in str(excinfo.value)
-@pytest.unsupported_on_pypy
-@pytest.requires_numpy
def test_vector_buffer_numpy():
+ np = pytest.importorskip("numpy")
a = np.array([1, 2, 3, 4], dtype=np.int32)
with pytest.raises(TypeError):
m.VectorInt(a)
@@ -110,13 +114,23 @@ def test_vector_buffer_numpy():
v = m.get_vectorstruct()
assert v[0].x == 5
ma = np.asarray(v)
- ma[1]['x'] = 99
+ ma[1]["x"] = 99
assert v[1].x == 99
- v = m.VectorStruct(np.zeros(3, dtype=np.dtype([('w', 'bool'), ('x', 'I'),
- ('y', 'float64'), ('z', 'bool')], align=True)))
+ v = m.VectorStruct(
+ np.zeros(
+ 3,
+ dtype=np.dtype(
+ [("w", "bool"), ("x", "I"), ("y", "float64"), ("z", "bool")], align=True
+ ),
+ )
+ )
assert len(v) == 3
+ b = np.array([1, 2, 3, 4], dtype=np.uint8)
+ v = m.VectorUChar(b[::2])
+ assert v[1] == 3
+
def test_vector_bool():
import pybind11_cross_module_tests as cm
@@ -143,31 +157,31 @@ def test_vector_custom():
def test_map_string_double():
mm = m.MapStringDouble()
- mm['a'] = 1
- mm['b'] = 2.5
+ mm["a"] = 1
+ mm["b"] = 2.5
- assert list(mm) == ['a', 'b']
- assert list(mm.items()) == [('a', 1), ('b', 2.5)]
+ assert list(mm) == ["a", "b"]
+ assert list(mm.items()) == [("a", 1), ("b", 2.5)]
assert str(mm) == "MapStringDouble{a: 1, b: 2.5}"
um = m.UnorderedMapStringDouble()
- um['ua'] = 1.1
- um['ub'] = 2.6
+ um["ua"] = 1.1
+ um["ub"] = 2.6
- assert sorted(list(um)) == ['ua', 'ub']
- assert sorted(list(um.items())) == [('ua', 1.1), ('ub', 2.6)]
+ assert sorted(list(um)) == ["ua", "ub"]
+ assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
assert "UnorderedMapStringDouble" in str(um)
def test_map_string_double_const():
mc = m.MapStringDoubleConst()
- mc['a'] = 10
- mc['b'] = 20.5
+ mc["a"] = 10
+ mc["b"] = 20.5
assert str(mc) == "MapStringDoubleConst{a: 10, b: 20.5}"
umc = m.UnorderedMapStringDoubleConst()
- umc['a'] = 11
- umc['b'] = 21.5
+ umc["a"] = 11
+ umc["b"] = 21.5
str(umc)
@@ -188,7 +202,7 @@ def test_noncopyable_containers():
i = 1
for j in dnc:
- assert(j.value == i)
+ assert j.value == i
i += 1
# std::map
@@ -221,7 +235,8 @@ def test_noncopyable_containers():
for j in range(0, 5):
assert nvnc[i][j].value == j + 1
- for k, v in nvnc.items():
+ # Note: maps do not have .values()
+ for _, v in nvnc.items():
for i, j in enumerate(v, start=1):
assert j.value == i
@@ -232,7 +247,7 @@ def test_noncopyable_containers():
assert nmnc[i][j].value == 10 * j
vsum = 0
- for k_o, v_o in nmnc.items():
+ for _, v_o in nmnc.items():
for k_i, v_i in v_o.items():
assert v_i.value == 10 * k_i
vsum += v_i.value
@@ -246,7 +261,7 @@ def test_noncopyable_containers():
assert numnc[i][j].value == 10 * j
vsum = 0
- for k_o, v_o in numnc.items():
+ for _, v_o in numnc.items():
for k_i, v_i in v_o.items():
assert v_i.value == 10 * k_i
vsum += v_i.value
@@ -256,21 +271,21 @@ def test_noncopyable_containers():
def test_map_delitem():
mm = m.MapStringDouble()
- mm['a'] = 1
- mm['b'] = 2.5
+ mm["a"] = 1
+ mm["b"] = 2.5
- assert list(mm) == ['a', 'b']
- assert list(mm.items()) == [('a', 1), ('b', 2.5)]
- del mm['a']
- assert list(mm) == ['b']
- assert list(mm.items()) == [('b', 2.5)]
+ assert list(mm) == ["a", "b"]
+ assert list(mm.items()) == [("a", 1), ("b", 2.5)]
+ del mm["a"]
+ assert list(mm) == ["b"]
+ assert list(mm.items()) == [("b", 2.5)]
um = m.UnorderedMapStringDouble()
- um['ua'] = 1.1
- um['ub'] = 2.6
-
- assert sorted(list(um)) == ['ua', 'ub']
- assert sorted(list(um.items())) == [('ua', 1.1), ('ub', 2.6)]
- del um['ua']
- assert sorted(list(um)) == ['ub']
- assert sorted(list(um.items())) == [('ub', 2.6)]
+ um["ua"] = 1.1
+ um["ub"] = 2.6
+
+ assert sorted(list(um)) == ["ua", "ub"]
+ assert sorted(list(um.items())) == [("ua", 1.1), ("ub", 2.6)]
+ del um["ua"]
+ assert sorted(list(um)) == ["ub"]
+ assert sorted(list(um.items())) == [("ub", 2.6)]
diff --git a/3rdparty/pybind11/tests/test_tagbased_polymorphic.cpp b/3rdparty/pybind11/tests/test_tagbased_polymorphic.cpp
index 272e460c..838a168d 100644
--- a/3rdparty/pybind11/tests/test_tagbased_polymorphic.cpp
+++ b/3rdparty/pybind11/tests/test_tagbased_polymorphic.cpp
@@ -12,6 +12,12 @@
struct Animal
{
+ // Make this type also a "standard" polymorphic type, to confirm that
+ // specializing polymorphic_type_hook using enable_if_t still works
+ // (https://github.com/pybind/pybind11/pull/2016/).
+ virtual ~Animal() = default;
+
+ // Enum for tag-based polymorphism.
enum class Kind {
Unknown = 0,
Dog = 100, Labrador, Chihuahua, LastDog = 199,
@@ -111,7 +117,7 @@ namespace pybind11 {
static const void *get(const itype *src, const std::type_info*& type)
{ type = src ? Animal::type_of_kind(src->kind) : nullptr; return src; }
};
-}
+} // namespace pybind11
TEST_SUBMODULE(tagbased_polymorphic, m) {
py::class_<Animal>(m, "Animal")
diff --git a/3rdparty/pybind11/tests/test_tagbased_polymorphic.py b/3rdparty/pybind11/tests/test_tagbased_polymorphic.py
index 2574d7de..64eb8a3c 100644
--- a/3rdparty/pybind11/tests/test_tagbased_polymorphic.py
+++ b/3rdparty/pybind11/tests/test_tagbased_polymorphic.py
@@ -1,19 +1,28 @@
+# -*- coding: utf-8 -*-
from pybind11_tests import tagbased_polymorphic as m
def test_downcast():
zoo = m.create_zoo()
assert [type(animal) for animal in zoo] == [
- m.Labrador, m.Dog, m.Chihuahua, m.Cat, m.Panther
+ m.Labrador,
+ m.Dog,
+ m.Chihuahua,
+ m.Cat,
+ m.Panther,
]
assert [animal.name for animal in zoo] == [
- "Fido", "Ginger", "Hertzl", "Tiger", "Leo"
+ "Fido",
+ "Ginger",
+ "Hertzl",
+ "Tiger",
+ "Leo",
]
zoo[1].sound = "woooooo"
assert [dog.bark() for dog in zoo[:3]] == [
"Labrador Fido goes WOOF!",
"Dog Ginger goes woooooo",
- "Chihuahua Hertzl goes iyiyiyiyiyi and runs in circles"
+ "Chihuahua Hertzl goes iyiyiyiyiyi and runs in circles",
]
assert [cat.purr() for cat in zoo[3:]] == ["mrowr", "mrrrRRRRRR"]
zoo[0].excitement -= 1000
diff --git a/3rdparty/pybind11/tests/test_union.py b/3rdparty/pybind11/tests/test_union.py
index e1866e70..2a2c12fb 100644
--- a/3rdparty/pybind11/tests/test_union.py
+++ b/3rdparty/pybind11/tests/test_union.py
@@ -1,3 +1,4 @@
+# -*- coding: utf-8 -*-
from pybind11_tests import union_ as m
diff --git a/3rdparty/pybind11/tests/test_virtual_functions.cpp b/3rdparty/pybind11/tests/test_virtual_functions.cpp
index ccf018d9..685d64a7 100644
--- a/3rdparty/pybind11/tests/test_virtual_functions.cpp
+++ b/3rdparty/pybind11/tests/test_virtual_functions.cpp
@@ -47,7 +47,7 @@ public:
int run(int value) override {
/* Generate wrapping code that enables native function overloading */
- PYBIND11_OVERLOAD(
+ PYBIND11_OVERRIDE(
int, /* Return type */
ExampleVirt, /* Parent class */
run, /* Name of function */
@@ -56,7 +56,7 @@ public:
}
bool run_bool() override {
- PYBIND11_OVERLOAD_PURE(
+ PYBIND11_OVERRIDE_PURE(
bool, /* Return type */
ExampleVirt, /* Parent class */
run_bool, /* Name of function */
@@ -66,7 +66,7 @@ public:
}
void pure_virtual() override {
- PYBIND11_OVERLOAD_PURE(
+ PYBIND11_OVERRIDE_PURE(
void, /* Return type */
ExampleVirt, /* Parent class */
pure_virtual, /* Name of function */
@@ -78,7 +78,7 @@ public:
// We can return reference types for compatibility with C++ virtual interfaces that do so, but
// note they have some significant limitations (see the documentation).
const std::string &get_string1() override {
- PYBIND11_OVERLOAD(
+ PYBIND11_OVERRIDE(
const std::string &, /* Return type */
ExampleVirt, /* Parent class */
get_string1, /* Name of function */
@@ -87,7 +87,7 @@ public:
}
const std::string *get_string2() override {
- PYBIND11_OVERLOAD(
+ PYBIND11_OVERRIDE(
const std::string *, /* Return type */
ExampleVirt, /* Parent class */
get_string2, /* Name of function */
@@ -129,7 +129,9 @@ private:
class NCVirt {
public:
- virtual ~NCVirt() { }
+ virtual ~NCVirt() = default;
+ NCVirt() = default;
+ NCVirt(const NCVirt&) = delete;
virtual NonCopyable get_noncopyable(int a, int b) { return NonCopyable(a, b); }
virtual Movable get_movable(int a, int b) = 0;
@@ -137,13 +139,13 @@ public:
std::string print_movable(int a, int b) { return get_movable(a, b).get_value(); }
};
class NCVirtTrampoline : public NCVirt {
-#if !defined(__INTEL_COMPILER)
+#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
NonCopyable get_noncopyable(int a, int b) override {
- PYBIND11_OVERLOAD(NonCopyable, NCVirt, get_noncopyable, a, b);
+ PYBIND11_OVERRIDE(NonCopyable, NCVirt, get_noncopyable, a, b);
}
#endif
Movable get_movable(int a, int b) override {
- PYBIND11_OVERLOAD_PURE(Movable, NCVirt, get_movable, a, b);
+ PYBIND11_OVERRIDE_PURE(Movable, NCVirt, get_movable, a, b);
}
};
@@ -151,11 +153,13 @@ struct Base {
/* for some reason MSVC2015 can't compile this if the function is pure virtual */
virtual std::string dispatch() const { return {}; };
virtual ~Base() = default;
+ Base() = default;
+ Base(const Base&) = delete;
};
struct DispatchIssue : Base {
- virtual std::string dispatch() const {
- PYBIND11_OVERLOAD_PURE(std::string, Base, dispatch, /* no arguments */);
+ std::string dispatch() const override {
+ PYBIND11_OVERRIDE_PURE(std::string, Base, dispatch, /* no arguments */);
}
};
@@ -183,7 +187,7 @@ static void test_gil_from_thread() {
// Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
// rather long).
-void initialize_inherited_virtuals(py::module &m);
+void initialize_inherited_virtuals(py::module_ &m);
TEST_SUBMODULE(virtual_functions, m) {
// test_override
@@ -201,7 +205,7 @@ TEST_SUBMODULE(virtual_functions, m) {
.def(py::init<int, int>());
// test_move_support
-#if !defined(__INTEL_COMPILER)
+#if !defined(__INTEL_COMPILER) && !defined(__CUDACC__) && !defined(__PGIC__)
py::class_<NCVirt, NCVirtTrampoline>(m, "NCVirt")
.def(py::init<>())
.def("get_noncopyable", &NCVirt::get_noncopyable)
@@ -221,19 +225,22 @@ TEST_SUBMODULE(virtual_functions, m) {
// don't invoke Python dispatch classes by default when instantiating C++ classes
// that were not extended on the Python side
struct A {
- virtual ~A() {}
+ A() = default;
+ A(const A&) = delete;
+ virtual ~A() = default;
virtual void f() { py::print("A.f()"); }
};
struct PyA : A {
PyA() { py::print("PyA.PyA()"); }
- ~PyA() { py::print("PyA.~PyA()"); }
+ PyA(const PyA&) = delete;
+ ~PyA() override { py::print("PyA.~PyA()"); }
void f() override {
py::print("PyA.f()");
// This convolution just gives a `void`, but tests that PYBIND11_TYPE() works to protect
// a type containing a ,
- PYBIND11_OVERLOAD(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f);
+ PYBIND11_OVERRIDE(PYBIND11_TYPE(typename std::enable_if<true, void>::type), A, f);
}
};
@@ -246,16 +253,19 @@ TEST_SUBMODULE(virtual_functions, m) {
// test_alias_delay_initialization2
// ... unless we explicitly request it, as in this example:
struct A2 {
- virtual ~A2() {}
+ A2() = default;
+ A2(const A2&) = delete;
+ virtual ~A2() = default;
virtual void f() { py::print("A2.f()"); }
};
struct PyA2 : A2 {
PyA2() { py::print("PyA2.PyA2()"); }
- ~PyA2() { py::print("PyA2.~PyA2()"); }
+ PyA2(const PyA2&) = delete;
+ ~PyA2() override { py::print("PyA2.~PyA2()"); }
void f() override {
py::print("PyA2.f()");
- PYBIND11_OVERLOAD(void, A2, f);
+ PYBIND11_OVERRIDE(void, A2, f);
}
};
@@ -282,6 +292,8 @@ TEST_SUBMODULE(virtual_functions, m) {
std::string v;
A a;
explicit OverrideTest(const std::string &v) : v{v} {}
+ OverrideTest() = default;
+ OverrideTest(const OverrideTest&) = delete;
virtual std::string str_value() { return v; }
virtual std::string &str_ref() { return v; }
virtual A A_value() { return a; }
@@ -292,19 +304,19 @@ TEST_SUBMODULE(virtual_functions, m) {
class PyOverrideTest : public OverrideTest {
public:
using OverrideTest::OverrideTest;
- std::string str_value() override { PYBIND11_OVERLOAD(std::string, OverrideTest, str_value); }
+ std::string str_value() override { PYBIND11_OVERRIDE(std::string, OverrideTest, str_value); }
// Not allowed (uncommenting should hit a static_assert failure): we can't get a reference
// to a python numeric value, since we only copy values in the numeric type caster:
-// std::string &str_ref() override { PYBIND11_OVERLOAD(std::string &, OverrideTest, str_ref); }
+// std::string &str_ref() override { PYBIND11_OVERRIDE(std::string &, OverrideTest, str_ref); }
// But we can work around it like this:
private:
std::string _tmp;
- std::string str_ref_helper() { PYBIND11_OVERLOAD(std::string, OverrideTest, str_ref); }
+ std::string str_ref_helper() { PYBIND11_OVERRIDE(std::string, OverrideTest, str_ref); }
public:
std::string &str_ref() override { return _tmp = str_ref_helper(); }
- A A_value() override { PYBIND11_OVERLOAD(A, OverrideTest, A_value); }
- A &A_ref() override { PYBIND11_OVERLOAD(A &, OverrideTest, A_ref); }
+ A A_value() override { PYBIND11_OVERRIDE(A, OverrideTest, A_value); }
+ A &A_ref() override { PYBIND11_OVERRIDE(A &, OverrideTest, A_ref); }
};
py::class_<OverrideTest::A>(m, "OverrideTest_A")
@@ -339,6 +351,8 @@ public: \
return say_something(1) + " " + std::to_string(unlucky_number()); \
}
A_METHODS
+ A_Repeat() = default;
+ A_Repeat(const A_Repeat&) = delete;
virtual ~A_Repeat() = default;
};
class B_Repeat : public A_Repeat {
@@ -364,7 +378,12 @@ D_METHODS
};
// Base classes for templated inheritance trampolines. Identical to the repeat-everything version:
-class A_Tpl { A_METHODS; virtual ~A_Tpl() = default; };
+class A_Tpl {
+ A_METHODS;
+ A_Tpl() = default;
+ A_Tpl(const A_Tpl&) = delete;
+ virtual ~A_Tpl() = default;
+};
class B_Tpl : public A_Tpl { B_METHODS };
class C_Tpl : public B_Tpl { C_METHODS };
class D_Tpl : public C_Tpl { D_METHODS };
@@ -374,29 +393,29 @@ class D_Tpl : public C_Tpl { D_METHODS };
class PyA_Repeat : public A_Repeat {
public:
using A_Repeat::A_Repeat;
- int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, A_Repeat, unlucky_number, ); }
- std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, A_Repeat, say_something, times); }
+ int unlucky_number() override { PYBIND11_OVERRIDE_PURE(int, A_Repeat, unlucky_number, ); }
+ std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, A_Repeat, say_something, times); }
};
class PyB_Repeat : public B_Repeat {
public:
using B_Repeat::B_Repeat;
- int unlucky_number() override { PYBIND11_OVERLOAD(int, B_Repeat, unlucky_number, ); }
- std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, B_Repeat, say_something, times); }
- double lucky_number() override { PYBIND11_OVERLOAD(double, B_Repeat, lucky_number, ); }
+ int unlucky_number() override { PYBIND11_OVERRIDE(int, B_Repeat, unlucky_number, ); }
+ std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, B_Repeat, say_something, times); }
+ double lucky_number() override { PYBIND11_OVERRIDE(double, B_Repeat, lucky_number, ); }
};
class PyC_Repeat : public C_Repeat {
public:
using C_Repeat::C_Repeat;
- int unlucky_number() override { PYBIND11_OVERLOAD(int, C_Repeat, unlucky_number, ); }
- std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, C_Repeat, say_something, times); }
- double lucky_number() override { PYBIND11_OVERLOAD(double, C_Repeat, lucky_number, ); }
+ int unlucky_number() override { PYBIND11_OVERRIDE(int, C_Repeat, unlucky_number, ); }
+ std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, C_Repeat, say_something, times); }
+ double lucky_number() override { PYBIND11_OVERRIDE(double, C_Repeat, lucky_number, ); }
};
class PyD_Repeat : public D_Repeat {
public:
using D_Repeat::D_Repeat;
- int unlucky_number() override { PYBIND11_OVERLOAD(int, D_Repeat, unlucky_number, ); }
- std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, D_Repeat, say_something, times); }
- double lucky_number() override { PYBIND11_OVERLOAD(double, D_Repeat, lucky_number, ); }
+ int unlucky_number() override { PYBIND11_OVERRIDE(int, D_Repeat, unlucky_number, ); }
+ std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, D_Repeat, say_something, times); }
+ double lucky_number() override { PYBIND11_OVERRIDE(double, D_Repeat, lucky_number, ); }
};
// Inheritance approach 2: templated trampoline classes.
@@ -417,15 +436,15 @@ template <class Base = A_Tpl>
class PyA_Tpl : public Base {
public:
using Base::Base; // Inherit constructors
- int unlucky_number() override { PYBIND11_OVERLOAD_PURE(int, Base, unlucky_number, ); }
- std::string say_something(unsigned times) override { PYBIND11_OVERLOAD(std::string, Base, say_something, times); }
+ int unlucky_number() override { PYBIND11_OVERRIDE_PURE(int, Base, unlucky_number, ); }
+ std::string say_something(unsigned times) override { PYBIND11_OVERRIDE(std::string, Base, say_something, times); }
};
template <class Base = B_Tpl>
class PyB_Tpl : public PyA_Tpl<Base> {
public:
using PyA_Tpl<Base>::PyA_Tpl; // Inherit constructors (via PyA_Tpl's inherited constructors)
- int unlucky_number() override { PYBIND11_OVERLOAD(int, Base, unlucky_number, ); }
- double lucky_number() override { PYBIND11_OVERLOAD(double, Base, lucky_number, ); }
+ int unlucky_number() override { PYBIND11_OVERRIDE(int, Base, unlucky_number, ); }
+ double lucky_number() override { PYBIND11_OVERRIDE(double, Base, lucky_number, ); }
};
// Since C_Tpl and D_Tpl don't declare any new virtual methods, we don't actually need these (we can
// use PyB_Tpl<C_Tpl> and PyB_Tpl<D_Tpl> for the trampoline classes instead):
@@ -440,7 +459,7 @@ public:
};
*/
-void initialize_inherited_virtuals(py::module &m) {
+void initialize_inherited_virtuals(py::module_ &m) {
// test_inherited_virtuals
// Method 1: repeat
diff --git a/3rdparty/pybind11/tests/test_virtual_functions.py b/3rdparty/pybind11/tests/test_virtual_functions.py
index 5ce9abd3..ae199301 100644
--- a/3rdparty/pybind11/tests/test_virtual_functions.py
+++ b/3rdparty/pybind11/tests/test_virtual_functions.py
@@ -1,7 +1,10 @@
+# -*- coding: utf-8 -*-
import pytest
-from pybind11_tests import virtual_functions as m
-from pybind11_tests import ConstructorStats
+import env # noqa: F401
+
+m = pytest.importorskip("pybind11_tests.virtual_functions")
+from pybind11_tests import ConstructorStats # noqa: E402
def test_override(capture, msg):
@@ -11,18 +14,18 @@ def test_override(capture, msg):
self.data = "Hello world"
def run(self, value):
- print('ExtendedExampleVirt::run(%i), calling parent..' % value)
+ print("ExtendedExampleVirt::run(%i), calling parent.." % value)
return super(ExtendedExampleVirt, self).run(value + 1)
def run_bool(self):
- print('ExtendedExampleVirt::run_bool()')
+ print("ExtendedExampleVirt::run_bool()")
return False
def get_string1(self):
return "override1"
def pure_virtual(self):
- print('ExtendedExampleVirt::pure_virtual(): %s' % self.data)
+ print("ExtendedExampleVirt::pure_virtual(): %s" % self.data)
class ExtendedExampleVirt2(ExtendedExampleVirt):
def __init__(self, state):
@@ -34,21 +37,30 @@ def test_override(capture, msg):
ex12 = m.ExampleVirt(10)
with capture:
assert m.runExampleVirt(ex12, 20) == 30
- assert capture == """
+ assert (
+ capture
+ == """
Original implementation of ExampleVirt::run(state=10, value=20, str1=default1, str2=default2)
""" # noqa: E501 line too long
+ )
with pytest.raises(RuntimeError) as excinfo:
m.runExampleVirtVirtual(ex12)
- assert msg(excinfo.value) == 'Tried to call pure virtual function "ExampleVirt::pure_virtual"'
+ assert (
+ msg(excinfo.value)
+ == 'Tried to call pure virtual function "ExampleVirt::pure_virtual"'
+ )
ex12p = ExtendedExampleVirt(10)
with capture:
assert m.runExampleVirt(ex12p, 20) == 32
- assert capture == """
+ assert (
+ capture
+ == """
ExtendedExampleVirt::run(20), calling parent..
Original implementation of ExampleVirt::run(state=11, value=21, str1=override1, str2=default2)
""" # noqa: E501 line too long
+ )
with capture:
assert m.runExampleVirtBool(ex12p) is False
assert capture == "ExtendedExampleVirt::run_bool()"
@@ -59,16 +71,19 @@ def test_override(capture, msg):
ex12p2 = ExtendedExampleVirt2(15)
with capture:
assert m.runExampleVirt(ex12p2, 50) == 68
- assert capture == """
+ assert (
+ capture
+ == """
ExtendedExampleVirt::run(50), calling parent..
Original implementation of ExampleVirt::run(state=17, value=51, str1=override1, str2=override2)
""" # noqa: E501 line too long
+ )
cstats = ConstructorStats.get(m.ExampleVirt)
assert cstats.alive() == 3
del ex12, ex12p, ex12p2
assert cstats.alive() == 0
- assert cstats.values() == ['10', '11', '17']
+ assert cstats.values() == ["10", "11", "17"]
assert cstats.copy_constructions == 0
assert cstats.move_constructions >= 0
@@ -79,6 +94,7 @@ def test_alias_delay_initialization1(capture):
If we just create and use an A instance directly, the trampoline initialization is
bypassed and we only initialize an A() instead (for performance reasons).
"""
+
class B(m.A):
def __init__(self):
super(B, self).__init__()
@@ -100,12 +116,15 @@ def test_alias_delay_initialization1(capture):
m.call_f(b)
del b
pytest.gc_collect()
- assert capture == """
+ assert (
+ capture
+ == """
PyA.PyA()
PyA.f()
In python f()
PyA.~PyA()
"""
+ )
def test_alias_delay_initialization2(capture):
@@ -115,6 +134,7 @@ def test_alias_delay_initialization2(capture):
performance penalty, it also allows us to do more things with the trampoline
class such as defining local variables and performing construction/destruction.
"""
+
class B2(m.A2):
def __init__(self):
super(B2, self).__init__()
@@ -132,7 +152,9 @@ def test_alias_delay_initialization2(capture):
m.call_f(a3)
del a3
pytest.gc_collect()
- assert capture == """
+ assert (
+ capture
+ == """
PyA2.PyA2()
PyA2.f()
A2.f()
@@ -142,6 +164,7 @@ def test_alias_delay_initialization2(capture):
A2.f()
PyA2.~PyA2()
"""
+ )
# Python subclass version
with capture:
@@ -149,18 +172,23 @@ def test_alias_delay_initialization2(capture):
m.call_f(b2)
del b2
pytest.gc_collect()
- assert capture == """
+ assert (
+ capture
+ == """
PyA2.PyA2()
PyA2.f()
In python B2.f()
PyA2.~PyA2()
"""
+ )
# PyPy: Reference count > 1 causes call with noncopyable instance
# to fail in ncv1.print_nc()
-@pytest.unsupported_on_pypy
-@pytest.mark.skipif(not hasattr(m, "NCVirt"), reason="NCVirt test broken on ICPC")
+@pytest.mark.xfail("env.PYPY")
+@pytest.mark.skipif(
+ not hasattr(m, "NCVirt"), reason="NCVirt does not work on Intel/PGI/NVCC compilers"
+)
def test_move_support():
class NCVirtExt(m.NCVirt):
def get_noncopyable(self, a, b):
@@ -199,8 +227,8 @@ def test_move_support():
del ncv1, ncv2
assert nc_stats.alive() == 0
assert mv_stats.alive() == 0
- assert nc_stats.values() == ['4', '9', '9', '9']
- assert mv_stats.values() == ['4', '5', '7', '7']
+ assert nc_stats.values() == ["4", "9", "9", "9"]
+ assert mv_stats.values() == ["4", "5", "7", "7"]
assert nc_stats.copy_constructions == 0
assert mv_stats.copy_constructions == 1
assert nc_stats.move_constructions >= 0
@@ -209,6 +237,7 @@ def test_move_support():
def test_dispatch_issue(msg):
"""#159: virtual function dispatch has problems with similar-named functions"""
+
class PyClass1(m.DispatchIssue):
def dispatch(self):
return "Yay.."
@@ -217,7 +246,10 @@ def test_dispatch_issue(msg):
def dispatch(self):
with pytest.raises(RuntimeError) as excinfo:
super(PyClass2, self).dispatch()
- assert msg(excinfo.value) == 'Tried to call pure virtual function "Base::dispatch"'
+ assert (
+ msg(excinfo.value)
+ == 'Tried to call pure virtual function "Base::dispatch"'
+ )
p = PyClass1()
return m.dispatch_issue_go(p)
@@ -333,7 +365,7 @@ def test_inherited_virtuals():
class DT(m.D_Tpl):
def say_something(self, times):
- return "DT says:" + (' quack' * times)
+ return "DT says:" + (" quack" * times)
def unlucky_number(self):
return 1234
@@ -349,7 +381,7 @@ def test_inherited_virtuals():
class DT2(DT):
def say_something(self, times):
- return "DT2: " + ('QUACK' * times)
+ return "DT2: " + ("QUACK" * times)
def unlucky_number(self):
return -3