Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
pybind11
Commits
e315e1fe
Unverified
Commit
e315e1fe
authored
Oct 04, 2021
by
Henry Schreiner
Browse files
Merge branch 'master' into stable
parents
71fd5241
97976c16
Changes
143
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
203 additions
and
75 deletions
+203
-75
pyproject.toml
pyproject.toml
+6
-0
setup.py
setup.py
+1
-1
tests/CMakeLists.txt
tests/CMakeLists.txt
+14
-6
tests/extra_setuptools/test_setuphelper.py
tests/extra_setuptools/test_setuphelper.py
+1
-1
tests/local_bindings.h
tests/local_bindings.h
+23
-4
tests/object.h
tests/object.h
+7
-3
tests/pybind11_cross_module_tests.cpp
tests/pybind11_cross_module_tests.cpp
+16
-2
tests/pybind11_tests.h
tests/pybind11_tests.h
+6
-10
tests/requirements.txt
tests/requirements.txt
+3
-3
tests/test_buffers.cpp
tests/test_buffers.cpp
+7
-3
tests/test_buffers.py
tests/test_buffers.py
+2
-3
tests/test_builtin_casters.cpp
tests/test_builtin_casters.cpp
+22
-14
tests/test_builtin_casters.py
tests/test_builtin_casters.py
+1
-2
tests/test_call_policies.py
tests/test_call_policies.py
+1
-2
tests/test_callbacks.cpp
tests/test_callbacks.cpp
+41
-2
tests/test_callbacks.py
tests/test_callbacks.py
+11
-4
tests/test_chrono.py
tests/test_chrono.py
+2
-1
tests/test_class.cpp
tests/test_class.cpp
+26
-10
tests/test_class.py
tests/test_class.py
+9
-2
tests/test_cmake_build/installed_embed/CMakeLists.txt
tests/test_cmake_build/installed_embed/CMakeLists.txt
+4
-2
No files found.
pyproject.toml
View file @
e315e1fe
...
...
@@ -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"
...
...
setup.py
View file @
e315e1fe
...
...
@@ -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
...
...
tests/CMakeLists.txt
View file @
e315e1fe
...
...
@@ -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.1
8
)
if
(
${
CMAKE_VERSION
}
VERSION_LESS 3.
2
1
)
cmake_policy
(
VERSION
${
CMAKE_MAJOR_VERSION
}
.
${
CMAKE_MINOR_VERSION
}
)
else
()
cmake_policy
(
VERSION 3.1
8
)
cmake_policy
(
VERSION 3.
2
1
)
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
${
EIGEN
3
_VERSION
_STRING
}
)
GIT_REPOSITORY
"
${
PYBIND11_EIGEN_REPO
}
"
GIT_TAG
"
${
PYBIND11_
EIGEN_VERSION
}
"
)
FetchContent_GetProperties
(
eigen
)
if
(
NOT eigen_POPULATED
)
...
...
tests/extra_setuptools/test_setuphelper.py
View file @
e315e1fe
# -*- coding: utf-8 -*-
import
os
import
sys
import
subprocess
import
sys
from
textwrap
import
dedent
import
pytest
...
...
tests/local_bindings.h
View file @
e315e1fe
...
...
@@ -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
}
{}
};
tests/object.h
View file @
e315e1fe
...
...
@@ -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
;
}
...
...
tests/pybind11_cross_module_tests.cpp
View file @
e315e1fe
...
...
@@ -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
);
...
...
tests/pybind11_tests.h
View file @
e315e1fe
#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
;
}
...
...
tests/requirements.txt
View file @
e315e1fe
...
...
@@ -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"
tests/test_buffers.cpp
View file @
e315e1fe
...
...
@@ -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
);
...
...
tests/test_buffers.py
View file @
e315e1fe
# -*- 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"
)
...
...
tests/test_builtin_casters.cpp
View file @
e315e1fe
...
...
@@ -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
;
});
...
...
tests/test_builtin_casters.py
View file @
e315e1fe
...
...
@@ -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
():
...
...
tests/test_call_policies.py
View file @
e315e1fe
...
...
@@ -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
)
...
...
tests/test_callbacks.cpp
View file @
e315e1fe
...
...
@@ -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
);
...
...
tests/test_callbacks.py
View file @
e315e1fe
# -*- 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"""
...
...
tests/test_chrono.py
View file @
e315e1fe
# -*- 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
():
...
...
tests/test_class.cpp
View file @
e315e1fe
...
...
@@ -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:
...
...
tests/test_class.py
View file @
e315e1fe
...
...
@@ -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
:
...
...
tests/test_cmake_build/installed_embed/CMakeLists.txt
View file @
e315e1fe
...
...
@@ -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
)
Prev
1
2
3
4
5
6
7
8
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment