Unverified Commit e315e1fe authored by Henry Schreiner's avatar Henry Schreiner
Browse files

Merge branch 'master' into stable

parents 71fd5241 97976c16
......@@ -15,6 +15,12 @@ ignore = [
"noxfile.py",
]
[tool.isort]
# Needs the compiled .so modules and env.py from tests
known_first_party = "env,pybind11_cross_module_tests,pybind11_tests,"
# For black compatibility
profile = "black"
[tool.mypy]
files = "pybind11"
python_version = "2.7"
......
......@@ -4,6 +4,7 @@
# Setup script for PyPI; use CMakeFile.txt to build extension modules
import contextlib
import io
import os
import re
import shutil
......@@ -11,7 +12,6 @@ import string
import subprocess
import sys
import tempfile
import io
import setuptools.command.sdist
......
......@@ -10,10 +10,10 @@ 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)
if(${CMAKE_VERSION} VERSION_LESS 3.21)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.18)
cmake_policy(VERSION 3.21)
endif()
# Only needed for CMake < 3.5 support
......@@ -104,6 +104,7 @@ set(PYBIND11_TEST_FILES
test_constants_and_functions.cpp
test_copy_move.cpp
test_custom_type_casters.cpp
test_custom_type_setup.cpp
test_docstring_options.cpp
test_eigen.cpp
test_enum.cpp
......@@ -129,6 +130,7 @@ set(PYBIND11_TEST_FILES
test_stl.cpp
test_stl_binders.cpp
test_tagbased_polymorphic.cpp
test_thread.cpp
test_union.cpp
test_virtual_functions.cpp)
......@@ -169,6 +171,14 @@ set(PYBIND11_CROSS_MODULE_TESTS test_exceptions.py test_local_bindings.py test_s
set(PYBIND11_CROSS_MODULE_GIL_TESTS test_gil_scoped.py)
set(PYBIND11_EIGEN_REPO
"https://gitlab.com/libeigen/eigen.git"
CACHE STRING "Eigen repository to use for tests")
# This hash is for 3.3.8, using a hash for security reasons
set(PYBIND11_EIGEN_VERSION
"dc252fbf00079ccab57948a164b1421703fe4361"
CACHE STRING "Eigen version to use for tests")
# 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"
# skip message).
......@@ -182,13 +192,11 @@ if(PYBIND11_TEST_FILES_EIGEN_I GREATER -1)
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})
GIT_REPOSITORY "${PYBIND11_EIGEN_REPO}"
GIT_TAG "${PYBIND11_EIGEN_VERSION}")
FetchContent_GetProperties(eigen)
if(NOT eigen_POPULATED)
......
# -*- coding: utf-8 -*-
import os
import sys
import subprocess
import sys
from textwrap import dedent
import pytest
......
......@@ -6,7 +6,7 @@
/// Simple class used to test py::local:
template <int> class LocalBase {
public:
LocalBase(int i) : i(i) { }
explicit LocalBase(int i) : i(i) { }
int i = -1;
};
......@@ -35,6 +35,25 @@ using NonLocalVec2 = std::vector<NonLocal2>;
using NonLocalMap = std::unordered_map<std::string, NonLocalType>;
using NonLocalMap2 = std::unordered_map<std::string, uint8_t>;
// Exception that will be caught via the module local translator.
class LocalException : public std::exception {
public:
explicit LocalException(const char * m) : message{m} {}
const char * what() const noexcept override {return message.c_str();}
private:
std::string message = "";
};
// Exception that will be registered with register_local_exception_translator
class LocalSimpleException : public std::exception {
public:
explicit LocalSimpleException(const char * m) : message{m} {}
const char * what() const noexcept override {return message.c_str();}
private:
std::string message = "";
};
PYBIND11_MAKE_OPAQUE(LocalVec);
PYBIND11_MAKE_OPAQUE(LocalVec2);
PYBIND11_MAKE_OPAQUE(LocalMap);
......@@ -56,11 +75,11 @@ py::class_<T> bind_local(Args && ...args) {
namespace pets {
class Pet {
public:
Pet(std::string name) : name_(std::move(name)) {}
explicit Pet(std::string name) : name_(std::move(name)) {}
std::string name_;
const std::string &name() const { return name_; }
};
} // namespace pets
struct MixGL { int i; MixGL(int i) : i{i} {} };
struct MixGL2 { int i; MixGL2(int i) : i{i} {} };
struct MixGL { int i; explicit MixGL(int i) : i{i} {} };
struct MixGL2 { int i; explicit MixGL2(int i) : i{i} {} };
......@@ -65,7 +65,7 @@ public:
ref() : m_ptr(nullptr) { print_default_created(this); track_default_created((ref_tag*) this); }
/// Construct a reference from a pointer
ref(T *ptr) : m_ptr(ptr) {
explicit ref(T *ptr) : m_ptr(ptr) {
if (m_ptr) ((Object *) m_ptr)->incRef();
print_created(this, "from pointer", m_ptr); track_created((ref_tag*) this, "from pointer");
......@@ -110,7 +110,11 @@ public:
/// Overwrite this reference with another reference
ref& operator=(const ref& r) {
print_copy_assigned(this, "pointer", r.m_ptr); track_copy_assigned((ref_tag*) this);
if (this == &r) {
return *this;
}
print_copy_assigned(this, "pointer", r.m_ptr);
track_copy_assigned((ref_tag *) this);
if (m_ptr == r.m_ptr)
return *this;
......@@ -161,7 +165,7 @@ public:
const T& operator*() const { return *m_ptr; }
/// Return a pointer to the referenced object
operator T* () { return m_ptr; }
explicit operator T* () { return m_ptr; }
/// Return a const pointer to the referenced object
T* get_ptr() { return m_ptr; }
......
......@@ -29,11 +29,14 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
bind_local<ExternalType2>(m, "ExternalType2", py::module_local());
// test_exceptions.py
py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException");
m.def("raise_runtime_error", []() { PyErr_SetString(PyExc_RuntimeError, "My runtime error"); throw py::error_already_set(); });
m.def("raise_value_error", []() { PyErr_SetString(PyExc_ValueError, "My value error"); throw py::error_already_set(); });
m.def("throw_pybind_value_error", []() { throw py::value_error("pybind11 value error"); });
m.def("throw_pybind_type_error", []() { throw py::type_error("pybind11 type error"); });
m.def("throw_stop_iteration", []() { throw py::stop_iteration(); });
m.def("throw_local_error", []() { throw LocalException("just local"); });
m.def("throw_local_simple_error", []() { throw LocalSimpleException("external mod"); });
py::register_exception_translator([](std::exception_ptr p) {
try {
if (p) std::rethrow_exception(p);
......@@ -42,6 +45,17 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
}
});
// translate the local exception into a key error but only in this module
py::register_local_exception_translator([](std::exception_ptr p) {
try {
if (p) {
std::rethrow_exception(p);
}
} catch (const LocalException &e) {
PyErr_SetString(PyExc_KeyError, e.what());
}
});
// test_local_bindings.py
// Local to both:
bind_local<LocalType, 1>(m, "LocalType", py::module_local())
......@@ -94,7 +108,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); });
// test_internal_locals_differ
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::registered_local_types_cpp(); });
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::get_local_internals().registered_types_cpp; });
// test_stl_caster_vs_stl_bind
py::bind_vector<std::vector<int>>(m, "VectorInt");
......@@ -109,7 +123,7 @@ PYBIND11_MODULE(pybind11_cross_module_tests, m) {
class Dog : public pets::Pet {
public:
Dog(std::string name) : Pet(std::move(name)) {}
explicit Dog(std::string name) : Pet(std::move(name)) {}
};
py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("name", &pets::Pet::name);
......
#pragma once
// This must be kept first for MSVC 2015.
// Do not remove the empty line between the #includes.
#include <pybind11/pybind11.h>
#include <pybind11/eval.h>
#if defined(_MSC_VER) && _MSC_VER < 1910
......@@ -19,15 +16,14 @@ class test_initializer {
using Initializer = void (*)(py::module_ &);
public:
test_initializer(Initializer init);
explicit test_initializer(Initializer init);
test_initializer(const char *submodule_name, Initializer init);
};
#define TEST_SUBMODULE(name, variable) \
void test_submodule_##name(py::module_ &); \
test_initializer name(#name, test_submodule_##name); \
void test_submodule_##name(py::module_ &variable)
#define TEST_SUBMODULE(name, variable) \
void test_submodule_##name(py::module_ &); \
test_initializer name(#name, test_submodule_##name); \
void test_submodule_##name(py::module_ &(variable))
/// Dummy type which is not exported anywhere -- something to trigger a conversion error
struct UnregisteredType { };
......@@ -36,7 +32,7 @@ struct UnregisteredType { };
class UserType {
public:
UserType() = default;
UserType(int i) : i(i) { }
explicit UserType(int i) : i(i) { }
int value() const { return i; }
void set(int set) { i = set; }
......
......@@ -2,11 +2,11 @@
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"
numpy==1.20.0; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.7" and python_version<"3.10"
numpy==1.21.2; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.7" and python_version<"3.10"
numpy==1.21.2; platform_python_implementation!="PyPy" and sys_platform=="linux" and python_version=="3.10"
pytest==4.6.9; python_version<"3.5"
pytest==6.1.2; python_version=="3.5"
pytest==6.2.1; python_version>="3.6" and python_version<="3.9"
pytest @ git+https://github.com/pytest-dev/pytest@c117bc350ec1e570672fda3b2ad234fd52e72b53; python_version>="3.10"
pytest==6.2.4; python_version>="3.6"
pytest-timeout
scipy==1.2.3; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version<"3.6"
scipy==1.5.4; (platform_python_implementation!="PyPy" or sys_platform=="linux") and python_version>="3.6" and python_version<"3.10"
......@@ -40,7 +40,11 @@ TEST_SUBMODULE(buffers, m) {
}
Matrix &operator=(const Matrix &s) {
print_copy_assigned(this, std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
if (this == &s) {
return *this;
}
print_copy_assigned(this,
std::to_string(m_rows) + "x" + std::to_string(m_cols) + " matrix");
delete[] m_data;
m_rows = s.m_rows;
m_cols = s.m_cols;
......@@ -118,7 +122,7 @@ TEST_SUBMODULE(buffers, m) {
// test_inherited_protocol
class SquareMatrix : public Matrix {
public:
SquareMatrix(py::ssize_t n) : Matrix(n, n) { }
explicit 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")
......@@ -169,7 +173,7 @@ TEST_SUBMODULE(buffers, m) {
struct BufferReadOnly {
const uint8_t value = 0;
BufferReadOnly(uint8_t value): value(value) {}
explicit BufferReadOnly(uint8_t value) : value(value) {}
py::buffer_info get_buffer_info() {
return py::buffer_info(&value, 1);
......
# -*- coding: utf-8 -*-
import ctypes
import io
import struct
import ctypes
import pytest
import env # noqa: F401
from pybind11_tests import buffers as m
from pybind11_tests import ConstructorStats
from pybind11_tests import buffers as m
np = pytest.importorskip("numpy")
......
......@@ -10,11 +10,6 @@
#include "pybind11_tests.h"
#include <pybind11/complex.h>
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4127) // warning C4127: Conditional expression is constant
#endif
struct ConstRefCasted {
int tag;
};
......@@ -30,16 +25,28 @@ class type_caster<ConstRefCasted> {
// cast operator.
bool load(handle, bool) { return true; }
operator ConstRefCasted &&() {
explicit operator ConstRefCasted &&() {
value = {1};
// NOLINTNEXTLINE(performance-move-const-arg)
return std::move(value);
}
operator ConstRefCasted&() { value = {2}; return value; }
operator ConstRefCasted*() { value = {3}; return &value; }
explicit operator ConstRefCasted &() {
value = {2};
return value;
}
explicit operator ConstRefCasted *() {
value = {3};
return &value;
}
operator const ConstRefCasted&() { value = {4}; return value; }
operator const ConstRefCasted*() { value = {5}; return &value; }
explicit operator const ConstRefCasted &() {
value = {4};
return value;
}
explicit operator const ConstRefCasted *() {
value = {5};
return &value;
}
// custom cast_op to explicitly propagate types to the conversion operators.
template <typename T_>
......@@ -73,7 +80,7 @@ TEST_SUBMODULE(builtin_casters, m) {
std::wstring wstr;
wstr.push_back(0x61); // a
wstr.push_back(0x2e18); // ⸘
if (sizeof(wchar_t) == 2) { wstr.push_back(mathbfA16_1); wstr.push_back(mathbfA16_2); } // 𝐀, utf16
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) { wstr.push_back(mathbfA16_1); wstr.push_back(mathbfA16_2); } // 𝐀, utf16
else { wstr.push_back((wchar_t) mathbfA32); } // 𝐀, utf32
wstr.push_back(0x7a); // z
......@@ -83,11 +90,12 @@ TEST_SUBMODULE(builtin_casters, m) {
m.def("good_wchar_string", [=]() { return wstr; }); // a‽𝐀z
m.def("bad_utf8_string", []() { return std::string("abc\xd0" "def"); });
m.def("bad_utf16_string", [=]() { return std::u16string({ b16, char16_t(0xd800), z16 }); });
#if PY_MAJOR_VERSION >= 3
// Under Python 2.7, invalid unicode UTF-32 characters don't appear to trigger UnicodeDecodeError
if (PY_MAJOR_VERSION >= 3)
m.def("bad_utf32_string", [=]() { return std::u32string({ a32, char32_t(0xd800), z32 }); });
if (PY_MAJOR_VERSION >= 3 || sizeof(wchar_t) == 2)
m.def("bad_utf32_string", [=]() { return std::u32string({ a32, char32_t(0xd800), z32 }); });
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2))
m.def("bad_wchar_string", [=]() { return std::wstring({ wchar_t(0x61), wchar_t(0xd800) }); });
#endif
m.def("u8_Z", []() -> char { return 'Z'; });
m.def("u8_eacute", []() -> char { return '\xe9'; });
m.def("u16_ibang", [=]() -> char16_t { return ib16; });
......
......@@ -2,9 +2,8 @@
import pytest
import env # noqa: F401
from pybind11_tests import IncType, UserType
from pybind11_tests import builtin_casters as m
from pybind11_tests import UserType, IncType
def test_simple_string():
......
......@@ -2,9 +2,8 @@
import pytest
import env # noqa: F401
from pybind11_tests import call_policies as m
from pybind11_tests import ConstructorStats
from pybind11_tests import call_policies as m
@pytest.mark.xfail("env.PYPY", reason="sometimes comes out 1 off on PyPy", strict=False)
......
......@@ -81,16 +81,55 @@ TEST_SUBMODULE(callbacks, m) {
};
// Export the payload constructor statistics for testing purposes:
m.def("payload_cstats", &ConstructorStats::get<Payload>);
/* Test cleanup of lambda closure */
m.def("test_cleanup", []() -> std::function<void()> {
m.def("test_lambda_closure_cleanup", []() -> std::function<void()> {
Payload p;
// In this situation, `Func` in the implementation of
// `cpp_function::initialize` is NOT trivially destructible.
return [p]() {
/* p should be cleaned up when the returned function is garbage collected */
(void) p;
};
});
class CppCallable {
public:
CppCallable() { track_default_created(this); }
~CppCallable() { track_destroyed(this); }
CppCallable(const CppCallable &) { track_copy_created(this); }
CppCallable(CppCallable &&) noexcept { track_move_created(this); }
void operator()() {}
};
m.def("test_cpp_callable_cleanup", []() {
// Related issue: https://github.com/pybind/pybind11/issues/3228
// Related PR: https://github.com/pybind/pybind11/pull/3229
py::list alive_counts;
ConstructorStats &stat = ConstructorStats::get<CppCallable>();
alive_counts.append(stat.alive());
{
CppCallable cpp_callable;
alive_counts.append(stat.alive());
{
// In this situation, `Func` in the implementation of
// `cpp_function::initialize` IS trivially destructible,
// only `capture` is not.
py::cpp_function py_func(cpp_callable);
py::detail::silence_unused_warnings(py_func);
alive_counts.append(stat.alive());
}
alive_counts.append(stat.alive());
{
py::cpp_function py_func(std::move(cpp_callable));
py::detail::silence_unused_warnings(py_func);
alive_counts.append(stat.alive());
}
alive_counts.append(stat.alive());
}
alive_counts.append(stat.alive());
return alive_counts;
});
// test_cpp_function_roundtrip
/* Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer */
m.def("dummy_function", &dummy_function);
......
# -*- coding: utf-8 -*-
import pytest
from pybind11_tests import callbacks as m
from threading import Thread
import time
from threading import Thread
import pytest
import env # NOQA: F401
from pybind11_tests import callbacks as m
def test_callbacks():
......@@ -77,13 +79,18 @@ def test_keyword_args_and_generalized_unpacking():
def test_lambda_closure_cleanup():
m.test_cleanup()
m.test_lambda_closure_cleanup()
cstats = m.payload_cstats()
assert cstats.alive() == 0
assert cstats.copy_constructions == 1
assert cstats.move_constructions >= 1
def test_cpp_callable_cleanup():
alive_counts = m.test_cpp_callable_cleanup()
assert alive_counts == [0, 1, 2, 1, 2, 1, 0]
def test_cpp_function_roundtrip():
"""Test if passing a function pointer from C++ -> Python -> C++ yields the original pointer"""
......
# -*- coding: utf-8 -*-
from pybind11_tests import chrono as m
import datetime
import pytest
import env # noqa: F401
from pybind11_tests import chrono as m
def test_chrono_system_clock():
......
......@@ -27,7 +27,7 @@
// test_brace_initialization
struct NoBraceInitialization {
NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
explicit NoBraceInitialization(std::vector<int> v) : vec{std::move(v)} {}
template <typename T>
NoBraceInitialization(std::initializer_list<T> l) : vec(l) {}
......@@ -47,10 +47,26 @@ TEST_SUBMODULE(class_, m) {
}
~NoConstructor() { print_destroyed(this); }
};
struct NoConstructorNew {
NoConstructorNew() = default;
NoConstructorNew(const NoConstructorNew &) = default;
NoConstructorNew(NoConstructorNew &&) = default;
static NoConstructorNew *new_instance() {
auto *ptr = new NoConstructorNew();
print_created(ptr, "via new_instance");
return ptr;
}
~NoConstructorNew() { print_destroyed(this); }
};
py::class_<NoConstructor>(m, "NoConstructor")
.def_static("new_instance", &NoConstructor::new_instance, "Return an instance");
py::class_<NoConstructorNew>(m, "NoConstructorNew")
.def(py::init([](const NoConstructorNew &self) { return self; })) // Need a NOOP __init__
.def_static("__new__",
[](const py::object &) { return NoConstructorNew::new_instance(); });
// test_inheritance
class Pet {
public:
......@@ -65,18 +81,18 @@ TEST_SUBMODULE(class_, m) {
class Dog : public Pet {
public:
Dog(const std::string &name) : Pet(name, "dog") {}
explicit Dog(const std::string &name) : Pet(name, "dog") {}
std::string bark() const { return "Woof!"; }
};
class Rabbit : public Pet {
public:
Rabbit(const std::string &name) : Pet(name, "parrot") {}
explicit Rabbit(const std::string &name) : Pet(name, "parrot") {}
};
class Hamster : public Pet {
public:
Hamster(const std::string &name) : Pet(name, "rodent") {}
explicit Hamster(const std::string &name) : Pet(name, "rodent") {}
};
class Chimera : public Pet {
......@@ -208,7 +224,7 @@ TEST_SUBMODULE(class_, m) {
struct ConvertibleFromUserType {
int i;
ConvertibleFromUserType(UserType u) : i(u.value()) { }
explicit ConvertibleFromUserType(UserType u) : i(u.value()) {}
};
py::class_<ConvertibleFromUserType>(m, "AcceptsUserType")
......@@ -263,7 +279,7 @@ TEST_SUBMODULE(class_, m) {
};
struct PyAliasedHasOpNewDelSize : AliasedHasOpNewDelSize {
PyAliasedHasOpNewDelSize() = default;
PyAliasedHasOpNewDelSize(int) { }
explicit PyAliasedHasOpNewDelSize(int) {}
std::uint64_t j;
};
struct HasOpNewDelBoth {
......@@ -492,15 +508,15 @@ 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, \
#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);
#define CHECK_ALIAS(N) static_assert(DoesntBreak##N::has_alias && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<N>>::value, \
#define CHECK_ALIAS(N) static_assert(DoesntBreak##N::has_alias && std::is_same<typename DoesntBreak##N::type_alias, BreaksTramp<(N)>>::value, \
"DoesntBreak" #N " has wrong type_alias!")
#define CHECK_NOALIAS(N) static_assert(!DoesntBreak##N::has_alias && std::is_void<typename DoesntBreak##N::type_alias>::value, \
"DoesntBreak" #N " has type alias, but shouldn't!")
CHECK_ALIAS(1); CHECK_ALIAS(2); CHECK_NOALIAS(3); CHECK_ALIAS(4); CHECK_NOALIAS(5); CHECK_ALIAS(6); CHECK_ALIAS(7); CHECK_NOALIAS(8);
#define CHECK_HOLDER(N, TYPE) static_assert(std::is_same<typename DoesntBreak##N::holder_type, std::TYPE##_ptr<BreaksBase<N>>>::value, \
#define CHECK_HOLDER(N, TYPE) static_assert(std::is_same<typename DoesntBreak##N::holder_type, std::TYPE##_ptr<BreaksBase<(N)>>>::value, \
"DoesntBreak" #N " has wrong holder_type!")
CHECK_HOLDER(1, unique); CHECK_HOLDER(2, unique); CHECK_HOLDER(3, unique); CHECK_HOLDER(4, unique); CHECK_HOLDER(5, unique);
CHECK_HOLDER(6, shared); CHECK_HOLDER(7, shared); CHECK_HOLDER(8, shared);
......@@ -510,7 +526,7 @@ CHECK_HOLDER(6, shared); CHECK_HOLDER(7, shared); CHECK_HOLDER(8, shared);
// failures occurs).
// We have to actually look into the type: the typedef alone isn't enough to instantiate the type:
#define CHECK_BROKEN(N) static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-N>>::value, \
#define CHECK_BROKEN(N) static_assert(std::is_same<typename Breaks##N::type, BreaksBase<-(N)>>::value, \
"Breaks1 has wrong type!");
//// Two holder classes:
......
......@@ -2,9 +2,8 @@
import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats, UserType
from pybind11_tests import class_ as m
from pybind11_tests import UserType, ConstructorStats
def test_repr():
......@@ -26,6 +25,14 @@ def test_instance(msg):
assert cstats.alive() == 0
def test_instance_new(msg):
instance = m.NoConstructorNew() # .__new__(m.NoConstructor.__class__)
cstats = ConstructorStats.get(m.NoConstructorNew)
assert cstats.alive() == 1
del instance
assert cstats.alive() == 0
def test_type():
assert m.check_type(1) == m.DerivedClass1
with pytest.raises(RuntimeError) as execinfo:
......
......@@ -22,5 +22,7 @@ set_target_properties(test_installed_embed PROPERTIES OUTPUT_NAME test_cmake_bui
# This may be needed to resolve header conflicts, e.g. between Python release and debug headers.
set_target_properties(test_installed_embed PROPERTIES NO_SYSTEM_FROM_IMPORTED ON)
add_custom_target(check_installed_embed $<TARGET_FILE:test_installed_embed>
${PROJECT_SOURCE_DIR}/../test.py)
add_custom_target(
check_installed_embed
$<TARGET_FILE:test_installed_embed> ${PROJECT_SOURCE_DIR}/../test.py
DEPENDS test_installed_embed)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment