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
93716147
Commit
93716147
authored
Dec 28, 2021
by
Henry Schreiner
Browse files
Merge branch 'master' into stable
parents
acae9301
45f792ef
Changes
57
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
350 additions
and
16 deletions
+350
-16
tests/test_buffers.py
tests/test_buffers.py
+4
-0
tests/test_builtin_casters.cpp
tests/test_builtin_casters.cpp
+25
-1
tests/test_builtin_casters.py
tests/test_builtin_casters.py
+16
-2
tests/test_copy_move.cpp
tests/test_copy_move.cpp
+3
-3
tests/test_custom_type_casters.cpp
tests/test_custom_type_casters.cpp
+8
-3
tests/test_embed/CMakeLists.txt
tests/test_embed/CMakeLists.txt
+1
-1
tests/test_embed/test_interpreter.cpp
tests/test_embed/test_interpreter.cpp
+49
-0
tests/test_embed/test_trampoline.py
tests/test_embed/test_trampoline.py
+18
-0
tests/test_exceptions.py
tests/test_exceptions.py
+3
-1
tests/test_kwargs_and_defaults.cpp
tests/test_kwargs_and_defaults.cpp
+34
-0
tests/test_kwargs_and_defaults.py
tests/test_kwargs_and_defaults.py
+110
-1
tests/test_methods_and_attributes.cpp
tests/test_methods_and_attributes.cpp
+15
-0
tests/test_methods_and_attributes.py
tests/test_methods_and_attributes.py
+8
-0
tests/test_virtual_functions.cpp
tests/test_virtual_functions.cpp
+25
-0
tests/test_virtual_functions.py
tests/test_virtual_functions.py
+19
-0
tools/pybind11Common.cmake
tools/pybind11Common.cmake
+10
-2
tools/pybind11Config.cmake.in
tools/pybind11Config.cmake.in
+2
-2
No files found.
tests/test_buffers.py
View file @
93716147
...
@@ -36,6 +36,10 @@ def test_from_python():
...
@@ -36,6 +36,10 @@ def test_from_python():
# https://foss.heptapod.net/pypy/pypy/-/issues/2444
# https://foss.heptapod.net/pypy/pypy/-/issues/2444
# TODO: fix on recent PyPy
@
pytest
.
mark
.
xfail
(
env
.
PYPY
,
reason
=
"PyPy 7.3.7 doesn't clear this anymore"
,
strict
=
False
)
def
test_to_python
():
def
test_to_python
():
mat
=
m
.
Matrix
(
5
,
4
)
mat
=
m
.
Matrix
(
5
,
4
)
assert
memoryview
(
mat
).
shape
==
(
5
,
4
)
assert
memoryview
(
mat
).
shape
==
(
5
,
4
)
...
...
tests/test_builtin_casters.cpp
View file @
93716147
...
@@ -19,7 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
...
@@ -19,7 +19,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
template
<
>
template
<
>
class
type_caster
<
ConstRefCasted
>
{
class
type_caster
<
ConstRefCasted
>
{
public:
public:
static
constexpr
auto
name
=
_
<
ConstRefCasted
>
();
static
constexpr
auto
name
=
const_name
<
ConstRefCasted
>
();
// Input is unimportant, a new value will always be constructed based on the
// Input is unimportant, a new value will always be constructed based on the
// cast operator.
// cast operator.
...
@@ -140,11 +140,35 @@ TEST_SUBMODULE(builtin_casters, m) {
...
@@ -140,11 +140,35 @@ TEST_SUBMODULE(builtin_casters, m) {
m
.
def
(
"string_view16_return"
,
[]()
{
return
std
::
u16string_view
(
u"utf16 secret \U0001f382"
);
});
m
.
def
(
"string_view16_return"
,
[]()
{
return
std
::
u16string_view
(
u"utf16 secret \U0001f382"
);
});
m
.
def
(
"string_view32_return"
,
[]()
{
return
std
::
u32string_view
(
U"utf32 secret \U0001f382"
);
});
m
.
def
(
"string_view32_return"
,
[]()
{
return
std
::
u32string_view
(
U"utf32 secret \U0001f382"
);
});
// The inner lambdas here are to also test implicit conversion
using
namespace
std
::
literals
;
m
.
def
(
"string_view_bytes"
,
[]()
{
return
[](
py
::
bytes
b
)
{
return
b
;
}(
"abc
\x80\x80
def"
sv
);
});
m
.
def
(
"string_view_str"
,
[]()
{
return
[](
py
::
str
s
)
{
return
s
;
}(
"abc
\342\200\275
def"
sv
);
});
m
.
def
(
"string_view_from_bytes"
,
[](
const
py
::
bytes
&
b
)
{
return
[](
std
::
string_view
s
)
{
return
s
;
}(
b
);
});
#if PY_MAJOR_VERSION >= 3
m
.
def
(
"string_view_memoryview"
,
[]()
{
static
constexpr
auto
val
=
"Have some
\360\237\216\202
"
sv
;
return
py
::
memoryview
::
from_memory
(
val
);
});
#endif
# ifdef PYBIND11_HAS_U8STRING
# ifdef PYBIND11_HAS_U8STRING
m
.
def
(
"string_view8_print"
,
[](
std
::
u8string_view
s
)
{
py
::
print
(
s
,
s
.
size
());
});
m
.
def
(
"string_view8_print"
,
[](
std
::
u8string_view
s
)
{
py
::
print
(
s
,
s
.
size
());
});
m
.
def
(
"string_view8_chars"
,
[](
std
::
u8string_view
s
)
{
py
::
list
l
;
for
(
auto
c
:
s
)
l
.
append
((
std
::
uint8_t
)
c
);
return
l
;
});
m
.
def
(
"string_view8_chars"
,
[](
std
::
u8string_view
s
)
{
py
::
list
l
;
for
(
auto
c
:
s
)
l
.
append
((
std
::
uint8_t
)
c
);
return
l
;
});
m
.
def
(
"string_view8_return"
,
[]()
{
return
std
::
u8string_view
(
u8"utf8 secret \U0001f382"
);
});
m
.
def
(
"string_view8_return"
,
[]()
{
return
std
::
u8string_view
(
u8"utf8 secret \U0001f382"
);
});
m
.
def
(
"string_view8_str"
,
[]()
{
return
py
::
str
{
std
::
u8string_view
{
u8"abc ‽ def"
}};
});
# endif
# endif
struct
TypeWithBothOperatorStringAndStringView
{
// NOLINTNEXTLINE(google-explicit-constructor)
operator
std
::
string
()
const
{
return
"success"
;
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator
std
::
string_view
()
const
{
return
"failure"
;
}
};
m
.
def
(
"bytes_from_type_with_both_operator_string_and_string_view"
,
[]()
{
return
py
::
bytes
(
TypeWithBothOperatorStringAndStringView
());
});
m
.
def
(
"str_from_type_with_both_operator_string_and_string_view"
,
[]()
{
return
py
::
str
(
TypeWithBothOperatorStringAndStringView
());
});
#endif
#endif
// test_integer_casting
// test_integer_casting
...
...
tests/test_builtin_casters.py
View file @
93716147
...
@@ -206,6 +206,17 @@ def test_string_view(capture):
...
@@ -206,6 +206,17 @@ def test_string_view(capture):
"""
"""
)
)
assert
m
.
string_view_bytes
()
==
b
"abc
\x80\x80
def"
assert
m
.
string_view_str
()
==
u
"abc ‽ def"
assert
m
.
string_view_from_bytes
(
u
"abc ‽ def"
.
encode
(
"utf-8"
))
==
u
"abc ‽ def"
if
hasattr
(
m
,
"has_u8string"
):
assert
m
.
string_view8_str
()
==
u
"abc ‽ def"
if
not
env
.
PY2
:
assert
m
.
string_view_memoryview
()
==
"Have some 🎂"
.
encode
()
assert
m
.
bytes_from_type_with_both_operator_string_and_string_view
()
==
b
"success"
assert
m
.
str_from_type_with_both_operator_string_and_string_view
()
==
"success"
def
test_integer_casting
():
def
test_integer_casting
():
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
...
@@ -299,7 +310,8 @@ def test_int_convert():
...
@@ -299,7 +310,8 @@ def test_int_convert():
assert
noconvert
(
7
)
==
7
assert
noconvert
(
7
)
==
7
cant_convert
(
3.14159
)
cant_convert
(
3.14159
)
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
if
(
3
,
8
)
<=
env
.
PY
<
(
3
,
10
):
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
if
(
3
,
8
)
<=
env
.
PY
<
(
3
,
10
)
and
env
.
CPYTHON
:
with
env
.
deprecated_call
():
with
env
.
deprecated_call
():
assert
convert
(
Int
())
==
42
assert
convert
(
Int
())
==
42
else
:
else
:
...
@@ -334,7 +346,9 @@ def test_numpy_int_convert():
...
@@ -334,7 +346,9 @@ def test_numpy_int_convert():
# The implicit conversion from np.float32 is undesirable but currently accepted.
# The implicit conversion from np.float32 is undesirable but currently accepted.
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
# TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
if
(
3
,
8
)
<=
env
.
PY
<
(
3
,
10
):
# TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
# https://github.com/pybind/pybind11/issues/3408
if
(
3
,
8
)
<=
env
.
PY
<
(
3
,
10
)
and
env
.
CPYTHON
:
with
env
.
deprecated_call
():
with
env
.
deprecated_call
():
assert
convert
(
np
.
float32
(
3.14159
))
==
3
assert
convert
(
np
.
float32
(
3.14159
))
==
3
else
:
else
:
...
...
tests/test_copy_move.cpp
View file @
93716147
...
@@ -85,13 +85,13 @@ public:
...
@@ -85,13 +85,13 @@ public:
PYBIND11_NAMESPACE_BEGIN
(
pybind11
)
PYBIND11_NAMESPACE_BEGIN
(
pybind11
)
PYBIND11_NAMESPACE_BEGIN
(
detail
)
PYBIND11_NAMESPACE_BEGIN
(
detail
)
template
<
>
struct
type_caster
<
MoveOnlyInt
>
{
template
<
>
struct
type_caster
<
MoveOnlyInt
>
{
PYBIND11_TYPE_CASTER
(
MoveOnlyInt
,
_
(
"MoveOnlyInt"
));
PYBIND11_TYPE_CASTER
(
MoveOnlyInt
,
const_name
(
"MoveOnlyInt"
));
bool
load
(
handle
src
,
bool
)
{
value
=
MoveOnlyInt
(
src
.
cast
<
int
>
());
return
true
;
}
bool
load
(
handle
src
,
bool
)
{
value
=
MoveOnlyInt
(
src
.
cast
<
int
>
());
return
true
;
}
static
handle
cast
(
const
MoveOnlyInt
&
m
,
return_value_policy
r
,
handle
p
)
{
return
pybind11
::
cast
(
m
.
value
,
r
,
p
);
}
static
handle
cast
(
const
MoveOnlyInt
&
m
,
return_value_policy
r
,
handle
p
)
{
return
pybind11
::
cast
(
m
.
value
,
r
,
p
);
}
};
};
template
<
>
struct
type_caster
<
MoveOrCopyInt
>
{
template
<
>
struct
type_caster
<
MoveOrCopyInt
>
{
PYBIND11_TYPE_CASTER
(
MoveOrCopyInt
,
_
(
"MoveOrCopyInt"
));
PYBIND11_TYPE_CASTER
(
MoveOrCopyInt
,
const_name
(
"MoveOrCopyInt"
));
bool
load
(
handle
src
,
bool
)
{
value
=
MoveOrCopyInt
(
src
.
cast
<
int
>
());
return
true
;
}
bool
load
(
handle
src
,
bool
)
{
value
=
MoveOrCopyInt
(
src
.
cast
<
int
>
());
return
true
;
}
static
handle
cast
(
const
MoveOrCopyInt
&
m
,
return_value_policy
r
,
handle
p
)
{
return
pybind11
::
cast
(
m
.
value
,
r
,
p
);
}
static
handle
cast
(
const
MoveOrCopyInt
&
m
,
return_value_policy
r
,
handle
p
)
{
return
pybind11
::
cast
(
m
.
value
,
r
,
p
);
}
};
};
...
@@ -100,7 +100,7 @@ template <> struct type_caster<CopyOnlyInt> {
...
@@ -100,7 +100,7 @@ template <> struct type_caster<CopyOnlyInt> {
protected:
protected:
CopyOnlyInt
value
;
CopyOnlyInt
value
;
public:
public:
static
constexpr
auto
name
=
_
(
"CopyOnlyInt"
);
static
constexpr
auto
name
=
const_name
(
"CopyOnlyInt"
);
bool
load
(
handle
src
,
bool
)
{
value
=
CopyOnlyInt
(
src
.
cast
<
int
>
());
return
true
;
}
bool
load
(
handle
src
,
bool
)
{
value
=
CopyOnlyInt
(
src
.
cast
<
int
>
());
return
true
;
}
static
handle
cast
(
const
CopyOnlyInt
&
m
,
return_value_policy
r
,
handle
p
)
{
return
pybind11
::
cast
(
m
.
value
,
r
,
p
);
}
static
handle
cast
(
const
CopyOnlyInt
&
m
,
return_value_policy
r
,
handle
p
)
{
return
pybind11
::
cast
(
m
.
value
,
r
,
p
);
}
static
handle
cast
(
const
CopyOnlyInt
*
src
,
return_value_policy
policy
,
handle
parent
)
{
static
handle
cast
(
const
CopyOnlyInt
*
src
,
return_value_policy
policy
,
handle
parent
)
{
...
...
tests/test_custom_type_casters.cpp
View file @
93716147
...
@@ -18,7 +18,12 @@ class ArgAlwaysConverts { };
...
@@ -18,7 +18,12 @@ class ArgAlwaysConverts { };
namespace
pybind11
{
namespace
detail
{
namespace
pybind11
{
namespace
detail
{
template
<
>
struct
type_caster
<
ArgInspector1
>
{
template
<
>
struct
type_caster
<
ArgInspector1
>
{
public:
public:
// Classic
#ifndef _
PYBIND11_TYPE_CASTER
(
ArgInspector1
,
_
(
"ArgInspector1"
));
PYBIND11_TYPE_CASTER
(
ArgInspector1
,
_
(
"ArgInspector1"
));
#else
PYBIND11_TYPE_CASTER
(
ArgInspector1
,
const_name
(
"ArgInspector1"
));
#endif
bool
load
(
handle
src
,
bool
convert
)
{
bool
load
(
handle
src
,
bool
convert
)
{
value
.
arg
=
"loading ArgInspector1 argument "
+
value
.
arg
=
"loading ArgInspector1 argument "
+
...
@@ -33,7 +38,7 @@ public:
...
@@ -33,7 +38,7 @@ public:
};
};
template
<
>
struct
type_caster
<
ArgInspector2
>
{
template
<
>
struct
type_caster
<
ArgInspector2
>
{
public:
public:
PYBIND11_TYPE_CASTER
(
ArgInspector2
,
_
(
"ArgInspector2"
));
PYBIND11_TYPE_CASTER
(
ArgInspector2
,
const_name
(
"ArgInspector2"
));
bool
load
(
handle
src
,
bool
convert
)
{
bool
load
(
handle
src
,
bool
convert
)
{
value
.
arg
=
"loading ArgInspector2 argument "
+
value
.
arg
=
"loading ArgInspector2 argument "
+
...
@@ -48,7 +53,7 @@ public:
...
@@ -48,7 +53,7 @@ public:
};
};
template
<
>
struct
type_caster
<
ArgAlwaysConverts
>
{
template
<
>
struct
type_caster
<
ArgAlwaysConverts
>
{
public:
public:
PYBIND11_TYPE_CASTER
(
ArgAlwaysConverts
,
_
(
"ArgAlwaysConverts"
));
PYBIND11_TYPE_CASTER
(
ArgAlwaysConverts
,
const_name
(
"ArgAlwaysConverts"
));
bool
load
(
handle
,
bool
convert
)
{
bool
load
(
handle
,
bool
convert
)
{
return
convert
;
return
convert
;
...
@@ -76,7 +81,7 @@ public:
...
@@ -76,7 +81,7 @@ public:
};
};
namespace
pybind11
{
namespace
detail
{
namespace
pybind11
{
namespace
detail
{
template
<
>
struct
type_caster
<
DestructionTester
>
{
template
<
>
struct
type_caster
<
DestructionTester
>
{
PYBIND11_TYPE_CASTER
(
DestructionTester
,
_
(
"DestructionTester"
));
PYBIND11_TYPE_CASTER
(
DestructionTester
,
const_name
(
"DestructionTester"
));
bool
load
(
handle
,
bool
)
{
return
true
;
}
bool
load
(
handle
,
bool
)
{
return
true
;
}
static
handle
cast
(
const
DestructionTester
&
,
return_value_policy
,
handle
)
{
static
handle
cast
(
const
DestructionTester
&
,
return_value_policy
,
handle
)
{
...
...
tests/test_embed/CMakeLists.txt
View file @
93716147
...
@@ -25,7 +25,7 @@ pybind11_enable_warnings(test_embed)
...
@@ -25,7 +25,7 @@ pybind11_enable_warnings(test_embed)
target_link_libraries
(
test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads
)
target_link_libraries
(
test_embed PRIVATE pybind11::embed Catch2::Catch2 Threads::Threads
)
if
(
NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR
)
if
(
NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR
)
file
(
COPY test_interpreter.py DESTINATION
"
${
CMAKE_CURRENT_BINARY_DIR
}
"
)
file
(
COPY test_interpreter.py
test_trampoline.py
DESTINATION
"
${
CMAKE_CURRENT_BINARY_DIR
}
"
)
endif
()
endif
()
add_custom_target
(
add_custom_target
(
...
...
tests/test_embed/test_interpreter.cpp
View file @
93716147
...
@@ -37,6 +37,22 @@ class PyWidget final : public Widget {
...
@@ -37,6 +37,22 @@ class PyWidget final : public Widget {
std
::
string
argv0
()
const
override
{
PYBIND11_OVERRIDE_PURE
(
std
::
string
,
Widget
,
argv0
);
}
std
::
string
argv0
()
const
override
{
PYBIND11_OVERRIDE_PURE
(
std
::
string
,
Widget
,
argv0
);
}
};
};
class
test_override_cache_helper
{
public:
virtual
int
func
()
{
return
0
;
}
test_override_cache_helper
()
=
default
;
virtual
~
test_override_cache_helper
()
=
default
;
// Non-copyable
test_override_cache_helper
&
operator
=
(
test_override_cache_helper
const
&
Right
)
=
delete
;
test_override_cache_helper
(
test_override_cache_helper
const
&
Copy
)
=
delete
;
};
class
test_override_cache_helper_trampoline
:
public
test_override_cache_helper
{
int
func
()
override
{
PYBIND11_OVERRIDE
(
int
,
test_override_cache_helper
,
func
);
}
};
PYBIND11_EMBEDDED_MODULE
(
widget_module
,
m
)
{
PYBIND11_EMBEDDED_MODULE
(
widget_module
,
m
)
{
py
::
class_
<
Widget
,
PyWidget
>
(
m
,
"Widget"
)
py
::
class_
<
Widget
,
PyWidget
>
(
m
,
"Widget"
)
.
def
(
py
::
init
<
std
::
string
>
())
.
def
(
py
::
init
<
std
::
string
>
())
...
@@ -45,6 +61,12 @@ PYBIND11_EMBEDDED_MODULE(widget_module, m) {
...
@@ -45,6 +61,12 @@ PYBIND11_EMBEDDED_MODULE(widget_module, m) {
m
.
def
(
"add"
,
[](
int
i
,
int
j
)
{
return
i
+
j
;
});
m
.
def
(
"add"
,
[](
int
i
,
int
j
)
{
return
i
+
j
;
});
}
}
PYBIND11_EMBEDDED_MODULE
(
trampoline_module
,
m
)
{
py
::
class_
<
test_override_cache_helper
,
test_override_cache_helper_trampoline
,
std
::
shared_ptr
<
test_override_cache_helper
>>
(
m
,
"test_override_cache_helper"
)
.
def
(
py
::
init_alias
<>
())
.
def
(
"func"
,
&
test_override_cache_helper
::
func
);
}
PYBIND11_EMBEDDED_MODULE
(
throw_exception
,
)
{
PYBIND11_EMBEDDED_MODULE
(
throw_exception
,
)
{
throw
std
::
runtime_error
(
"C++ Error"
);
throw
std
::
runtime_error
(
"C++ Error"
);
}
}
...
@@ -73,6 +95,33 @@ TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
...
@@ -73,6 +95,33 @@ TEST_CASE("Pass classes and data between modules defined in C++ and Python") {
REQUIRE
(
cpp_widget
.
the_answer
()
==
42
);
REQUIRE
(
cpp_widget
.
the_answer
()
==
42
);
}
}
TEST_CASE
(
"Override cache"
)
{
auto
module_
=
py
::
module_
::
import
(
"test_trampoline"
);
REQUIRE
(
py
::
hasattr
(
module_
,
"func"
));
REQUIRE
(
py
::
hasattr
(
module_
,
"func2"
));
auto
locals
=
py
::
dict
(
**
module_
.
attr
(
"__dict__"
));
int
i
=
0
;
for
(;
i
<
1500
;
++
i
)
{
std
::
shared_ptr
<
test_override_cache_helper
>
p_obj
;
std
::
shared_ptr
<
test_override_cache_helper
>
p_obj2
;
py
::
object
loc_inst
=
locals
[
"func"
]();
p_obj
=
py
::
cast
<
std
::
shared_ptr
<
test_override_cache_helper
>>
(
loc_inst
);
int
ret
=
p_obj
->
func
();
REQUIRE
(
ret
==
42
);
loc_inst
=
locals
[
"func2"
]();
p_obj2
=
py
::
cast
<
std
::
shared_ptr
<
test_override_cache_helper
>>
(
loc_inst
);
p_obj2
->
func
();
}
}
TEST_CASE
(
"Import error handling"
)
{
TEST_CASE
(
"Import error handling"
)
{
REQUIRE_NOTHROW
(
py
::
module_
::
import
(
"widget_module"
));
REQUIRE_NOTHROW
(
py
::
module_
::
import
(
"widget_module"
));
REQUIRE_THROWS_WITH
(
py
::
module_
::
import
(
"throw_exception"
),
REQUIRE_THROWS_WITH
(
py
::
module_
::
import
(
"throw_exception"
),
...
...
tests/test_embed/test_trampoline.py
0 → 100644
View file @
93716147
# -*- coding: utf-8 -*-
import
trampoline_module
def
func
():
class
Test
(
trampoline_module
.
test_override_cache_helper
):
def
func
(
self
):
return
42
return
Test
()
def
func2
():
class
Test
(
trampoline_module
.
test_override_cache_helper
):
pass
return
Test
()
tests/test_exceptions.py
View file @
93716147
...
@@ -3,7 +3,7 @@ import sys
...
@@ -3,7 +3,7 @@ import sys
import
pytest
import
pytest
import
env
# noqa: F401
import
env
import
pybind11_cross_module_tests
as
cm
import
pybind11_cross_module_tests
as
cm
from
pybind11_tests
import
exceptions
as
m
from
pybind11_tests
import
exceptions
as
m
...
@@ -97,6 +97,8 @@ def ignore_pytest_unraisable_warning(f):
...
@@ -97,6 +97,8 @@ def ignore_pytest_unraisable_warning(f):
return
f
return
f
# TODO: find out why this fails on PyPy, https://foss.heptapod.net/pypy/pypy/-/issues/3583
@
pytest
.
mark
.
xfail
(
env
.
PYPY
,
reason
=
"Failure on PyPy 3.8 (7.3.7)"
,
strict
=
False
)
@
ignore_pytest_unraisable_warning
@
ignore_pytest_unraisable_warning
def
test_python_alreadyset_in_destructor
(
monkeypatch
,
capsys
):
def
test_python_alreadyset_in_destructor
(
monkeypatch
,
capsys
):
hooked
=
False
hooked
=
False
...
...
tests/test_kwargs_and_defaults.cpp
View file @
93716147
...
@@ -56,6 +56,23 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
...
@@ -56,6 +56,23 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
m
.
def
(
"mixed_plus_args_kwargs_defaults"
,
mixed_plus_both
,
m
.
def
(
"mixed_plus_args_kwargs_defaults"
,
mixed_plus_both
,
py
::
arg
(
"i"
)
=
1
,
py
::
arg
(
"j"
)
=
3.14159
);
py
::
arg
(
"i"
)
=
1
,
py
::
arg
(
"j"
)
=
3.14159
);
m
.
def
(
"args_kwonly"
,
[](
int
i
,
double
j
,
const
py
::
args
&
args
,
int
z
)
{
return
py
::
make_tuple
(
i
,
j
,
args
,
z
);
},
"i"
_a
,
"j"
_a
,
"z"
_a
);
m
.
def
(
"args_kwonly_kwargs"
,
[](
int
i
,
double
j
,
const
py
::
args
&
args
,
int
z
,
const
py
::
kwargs
&
kwargs
)
{
return
py
::
make_tuple
(
i
,
j
,
args
,
z
,
kwargs
);
},
"i"
_a
,
"j"
_a
,
py
::
kw_only
{},
"z"
_a
);
m
.
def
(
"args_kwonly_kwargs_defaults"
,
[](
int
i
,
double
j
,
const
py
::
args
&
args
,
int
z
,
const
py
::
kwargs
&
kwargs
)
{
return
py
::
make_tuple
(
i
,
j
,
args
,
z
,
kwargs
);
},
"i"
_a
=
1
,
"j"
_a
=
3.14159
,
"z"
_a
=
42
);
m
.
def
(
"args_kwonly_full_monty"
,
[](
int
h
,
int
i
,
double
j
,
const
py
::
args
&
args
,
int
z
,
const
py
::
kwargs
&
kwargs
)
{
return
py
::
make_tuple
(
h
,
i
,
j
,
args
,
z
,
kwargs
);
},
py
::
arg
()
=
1
,
py
::
arg
()
=
2
,
py
::
pos_only
{},
"j"
_a
=
3.14159
,
"z"
_a
=
42
);
// test_args_refcount
// test_args_refcount
// PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
// PyPy needs a garbage collection to get the reference count values to match CPython's behaviour
#ifdef PYPY_VERSION
#ifdef PYPY_VERSION
...
@@ -150,4 +167,21 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
...
@@ -150,4 +167,21 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
"class_default_argument"
,
"class_default_argument"
,
[](
py
::
object
a
)
{
return
py
::
repr
(
std
::
move
(
a
));
},
[](
py
::
object
a
)
{
return
py
::
repr
(
std
::
move
(
a
));
},
"a"
_a
=
py
::
module_
::
import
(
"decimal"
).
attr
(
"Decimal"
));
"a"
_a
=
py
::
module_
::
import
(
"decimal"
).
attr
(
"Decimal"
));
// Initial implementation of kw_only was broken when used on a method/constructor before any
// other arguments
// https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
struct
first_arg_kw_only
{};
py
::
class_
<
first_arg_kw_only
>
(
m
,
"first_arg_kw_only"
)
.
def
(
py
::
init
([](
int
)
{
return
first_arg_kw_only
();
}),
py
::
kw_only
(),
// This being before any args was broken
py
::
arg
(
"i"
)
=
0
)
.
def
(
"method"
,
[](
first_arg_kw_only
&
,
int
,
int
)
{},
py
::
kw_only
(),
// and likewise here
py
::
arg
(
"i"
)
=
1
,
py
::
arg
(
"j"
)
=
2
)
// Closely related: pos_only marker didn't show up properly when it was before any other
// arguments (although that is fairly useless in practice).
.
def
(
"pos_only"
,
[](
first_arg_kw_only
&
,
int
,
int
)
{},
py
::
pos_only
{},
py
::
arg
(
"i"
),
py
::
arg
(
"j"
));
}
}
tests/test_kwargs_and_defaults.py
View file @
93716147
...
@@ -141,6 +141,53 @@ def test_mixed_args_and_kwargs(msg):
...
@@ -141,6 +141,53 @@ def test_mixed_args_and_kwargs(msg):
"""
# noqa: E501 line too long
"""
# noqa: E501 line too long
)
)
# Arguments after a py::args are automatically keyword-only (pybind 2.9+)
assert
m
.
args_kwonly
(
2
,
2.5
,
z
=
22
)
==
(
2
,
2.5
,
(),
22
)
assert
m
.
args_kwonly
(
2
,
2.5
,
"a"
,
"b"
,
"c"
,
z
=
22
)
==
(
2
,
2.5
,
(
"a"
,
"b"
,
"c"
),
22
)
assert
m
.
args_kwonly
(
z
=
22
,
i
=
4
,
j
=
16
)
==
(
4
,
16
,
(),
22
)
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
assert
m
.
args_kwonly
(
2
,
2.5
,
22
)
# missing z= keyword
assert
(
msg
(
excinfo
.
value
)
==
"""
args_kwonly(): incompatible function arguments. The following argument types are supported:
1. (i: int, j: float, *args, z: int) -> tuple
Invoked with: 2, 2.5, 22
"""
)
assert
m
.
args_kwonly_kwargs
(
i
=
1
,
k
=
4
,
j
=
10
,
z
=-
1
,
y
=
9
)
==
(
1
,
10
,
(),
-
1
,
{
"k"
:
4
,
"y"
:
9
},
)
assert
m
.
args_kwonly_kwargs
(
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
z
=
11
,
y
=
12
)
==
(
1
,
2
,
(
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
),
11
,
{
"y"
:
12
},
)
assert
(
m
.
args_kwonly_kwargs
.
__doc__
==
"args_kwonly_kwargs(i: int, j: float, *args, z: int, **kwargs) -> tuple
\n
"
)
assert
(
m
.
args_kwonly_kwargs_defaults
.
__doc__
==
"args_kwonly_kwargs_defaults(i: int = 1, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple
\n
"
# noqa: E501 line too long
)
assert
m
.
args_kwonly_kwargs_defaults
()
==
(
1
,
3.14159
,
(),
42
,
{})
assert
m
.
args_kwonly_kwargs_defaults
(
2
)
==
(
2
,
3.14159
,
(),
42
,
{})
assert
m
.
args_kwonly_kwargs_defaults
(
z
=-
99
)
==
(
1
,
3.14159
,
(),
-
99
,
{})
assert
m
.
args_kwonly_kwargs_defaults
(
5
,
6
,
7
,
8
)
==
(
5
,
6
,
(
7
,
8
),
42
,
{})
assert
m
.
args_kwonly_kwargs_defaults
(
5
,
6
,
7
,
m
=
8
)
==
(
5
,
6
,
(
7
,),
42
,
{
"m"
:
8
})
assert
m
.
args_kwonly_kwargs_defaults
(
5
,
6
,
7
,
m
=
8
,
z
=
9
)
==
(
5
,
6
,
(
7
,),
9
,
{
"m"
:
8
})
def
test_keyword_only_args
(
msg
):
def
test_keyword_only_args
(
msg
):
assert
m
.
kw_only_all
(
i
=
1
,
j
=
2
)
==
(
1
,
2
)
assert
m
.
kw_only_all
(
i
=
1
,
j
=
2
)
==
(
1
,
2
)
...
@@ -178,10 +225,23 @@ def test_keyword_only_args(msg):
...
@@ -178,10 +225,23 @@ def test_keyword_only_args(msg):
assert
(
assert
(
msg
(
excinfo
.
value
)
msg
(
excinfo
.
value
)
==
"""
==
"""
arg(): cannot specify an unnamed argument after a
n
kw_only() annotation
arg(): cannot specify an unnamed argument after a kw_only() annotation
or args() argument
"""
"""
)
)
# https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
x
=
m
.
first_arg_kw_only
(
i
=
1
)
x
.
method
()
x
.
method
(
i
=
1
,
j
=
2
)
assert
(
m
.
first_arg_kw_only
.
__init__
.
__doc__
==
"__init__(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 0) -> None
\n
"
# noqa: E501 line too long
)
assert
(
m
.
first_arg_kw_only
.
method
.
__doc__
==
"method(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, *, i: int = 1, j: int = 2) -> None
\n
"
# noqa: E501 line too long
)
def
test_positional_only_args
(
msg
):
def
test_positional_only_args
(
msg
):
assert
m
.
pos_only_all
(
1
,
2
)
==
(
1
,
2
)
assert
m
.
pos_only_all
(
1
,
2
)
==
(
1
,
2
)
...
@@ -222,6 +282,55 @@ def test_positional_only_args(msg):
...
@@ -222,6 +282,55 @@ def test_positional_only_args(msg):
m
.
pos_only_def_mix
(
1
,
j
=
4
)
m
.
pos_only_def_mix
(
1
,
j
=
4
)
assert
"incompatible function arguments"
in
str
(
excinfo
.
value
)
assert
"incompatible function arguments"
in
str
(
excinfo
.
value
)
# Mix it with args and kwargs:
assert
(
m
.
args_kwonly_full_monty
.
__doc__
==
"args_kwonly_full_monty(arg0: int = 1, arg1: int = 2, /, j: float = 3.14159, *args, z: int = 42, **kwargs) -> tuple
\n
"
# noqa: E501 line too long
)
assert
m
.
args_kwonly_full_monty
()
==
(
1
,
2
,
3.14159
,
(),
42
,
{})
assert
m
.
args_kwonly_full_monty
(
8
)
==
(
8
,
2
,
3.14159
,
(),
42
,
{})
assert
m
.
args_kwonly_full_monty
(
8
,
9
)
==
(
8
,
9
,
3.14159
,
(),
42
,
{})
assert
m
.
args_kwonly_full_monty
(
8
,
9
,
10
)
==
(
8
,
9
,
10.0
,
(),
42
,
{})
assert
m
.
args_kwonly_full_monty
(
3
,
4
,
5
,
6
,
7
,
m
=
8
,
z
=
9
)
==
(
3
,
4
,
5.0
,
(
6
,
7
,
),
9
,
{
"m"
:
8
},
)
assert
m
.
args_kwonly_full_monty
(
3
,
4
,
5
,
6
,
7
,
m
=
8
,
z
=
9
)
==
(
3
,
4
,
5.0
,
(
6
,
7
,
),
9
,
{
"m"
:
8
},
)
assert
m
.
args_kwonly_full_monty
(
5
,
j
=
7
,
m
=
8
,
z
=
9
)
==
(
5
,
2
,
7.0
,
(),
9
,
{
"m"
:
8
})
assert
m
.
args_kwonly_full_monty
(
i
=
5
,
j
=
7
,
m
=
8
,
z
=
9
)
==
(
1
,
2
,
7.0
,
(),
9
,
{
"i"
:
5
,
"m"
:
8
},
)
# pos_only at the beginning of the argument list was "broken" in how it was displayed (though
# this is fairly useless in practice). Related to:
# https://github.com/pybind/pybind11/pull/3402#issuecomment-963341987
assert
(
m
.
first_arg_kw_only
.
pos_only
.
__doc__
==
"pos_only(self: pybind11_tests.kwargs_and_defaults.first_arg_kw_only, /, i: int, j: int) -> None
\n
"
# noqa: E501 line too long
)
def
test_signatures
():
def
test_signatures
():
assert
"kw_only_all(*, i: int, j: int) -> tuple
\n
"
==
m
.
kw_only_all
.
__doc__
assert
"kw_only_all(*, i: int, j: int) -> tuple
\n
"
==
m
.
kw_only_all
.
__doc__
...
...
tests/test_methods_and_attributes.cpp
View file @
93716147
...
@@ -159,6 +159,14 @@ struct RefQualified {
...
@@ -159,6 +159,14 @@ struct RefQualified {
int
constRefQualified
(
int
other
)
const
&
{
return
value
+
other
;
}
int
constRefQualified
(
int
other
)
const
&
{
return
value
+
other
;
}
};
};
// Test rvalue ref param
struct
RValueRefParam
{
std
::
size_t
func1
(
std
::
string
&&
s
)
{
return
s
.
size
();
}
std
::
size_t
func2
(
std
::
string
&&
s
)
const
{
return
s
.
size
();
}
std
::
size_t
func3
(
std
::
string
&&
s
)
&
{
return
s
.
size
();
}
std
::
size_t
func4
(
std
::
string
&&
s
)
const
&
{
return
s
.
size
();
}
};
TEST_SUBMODULE
(
methods_and_attributes
,
m
)
{
TEST_SUBMODULE
(
methods_and_attributes
,
m
)
{
// test_methods_and_attributes
// test_methods_and_attributes
py
::
class_
<
ExampleMandA
>
emna
(
m
,
"ExampleMandA"
);
py
::
class_
<
ExampleMandA
>
emna
(
m
,
"ExampleMandA"
);
...
@@ -409,4 +417,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
...
@@ -409,4 +417,11 @@ TEST_SUBMODULE(methods_and_attributes, m) {
.
def_readonly
(
"value"
,
&
RefQualified
::
value
)
.
def_readonly
(
"value"
,
&
RefQualified
::
value
)
.
def
(
"refQualified"
,
&
RefQualified
::
refQualified
)
.
def
(
"refQualified"
,
&
RefQualified
::
refQualified
)
.
def
(
"constRefQualified"
,
&
RefQualified
::
constRefQualified
);
.
def
(
"constRefQualified"
,
&
RefQualified
::
constRefQualified
);
py
::
class_
<
RValueRefParam
>
(
m
,
"RValueRefParam"
)
.
def
(
py
::
init
<>
())
.
def
(
"func1"
,
&
RValueRefParam
::
func1
)
.
def
(
"func2"
,
&
RValueRefParam
::
func2
)
.
def
(
"func3"
,
&
RValueRefParam
::
func3
)
.
def
(
"func4"
,
&
RValueRefParam
::
func4
);
}
}
tests/test_methods_and_attributes.py
View file @
93716147
...
@@ -515,3 +515,11 @@ def test_overload_ordering():
...
@@ -515,3 +515,11 @@ def test_overload_ordering():
assert
"2. (arg0: {}) -> int"
.
format
(
uni_name
)
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
"3. (arg0: {}) -> int"
.
format
(
uni_name
)
in
str
(
err
.
value
)
assert
"4. (arg0: int) -> int"
in
str
(
err
.
value
)
assert
"4. (arg0: int) -> int"
in
str
(
err
.
value
)
def
test_rvalue_ref_param
():
r
=
m
.
RValueRefParam
()
assert
r
.
func1
(
"123"
)
==
3
assert
r
.
func2
(
"1234"
)
==
4
assert
r
.
func3
(
"12345"
)
==
5
assert
r
.
func4
(
"123456"
)
==
6
tests/test_virtual_functions.cpp
View file @
93716147
...
@@ -214,6 +214,25 @@ static void test_gil_from_thread() {
...
@@ -214,6 +214,25 @@ static void test_gil_from_thread() {
t
.
join
();
t
.
join
();
}
}
class
test_override_cache_helper
{
public:
virtual
int
func
()
{
return
0
;
}
test_override_cache_helper
()
=
default
;
virtual
~
test_override_cache_helper
()
=
default
;
// Non-copyable
test_override_cache_helper
&
operator
=
(
test_override_cache_helper
const
&
Right
)
=
delete
;
test_override_cache_helper
(
test_override_cache_helper
const
&
Copy
)
=
delete
;
};
class
test_override_cache_helper_trampoline
:
public
test_override_cache_helper
{
int
func
()
override
{
PYBIND11_OVERRIDE
(
int
,
test_override_cache_helper
,
func
);
}
};
inline
int
test_override_cache
(
std
::
shared_ptr
<
test_override_cache_helper
>
const
&
instance
)
{
return
instance
->
func
();
}
// Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
// Forward declaration (so that we can put the main tests here; the inherited virtual approaches are
// rather long).
// rather long).
...
@@ -378,6 +397,12 @@ TEST_SUBMODULE(virtual_functions, m) {
...
@@ -378,6 +397,12 @@ TEST_SUBMODULE(virtual_functions, m) {
// .def("str_ref", &OverrideTest::str_ref)
// .def("str_ref", &OverrideTest::str_ref)
.
def
(
"A_value"
,
&
OverrideTest
::
A_value
)
.
def
(
"A_value"
,
&
OverrideTest
::
A_value
)
.
def
(
"A_ref"
,
&
OverrideTest
::
A_ref
);
.
def
(
"A_ref"
,
&
OverrideTest
::
A_ref
);
py
::
class_
<
test_override_cache_helper
,
test_override_cache_helper_trampoline
,
std
::
shared_ptr
<
test_override_cache_helper
>>
(
m
,
"test_override_cache_helper"
)
.
def
(
py
::
init_alias
<>
())
.
def
(
"func"
,
&
test_override_cache_helper
::
func
);
m
.
def
(
"test_override_cache"
,
test_override_cache
);
}
}
...
...
tests/test_virtual_functions.py
View file @
93716147
...
@@ -439,3 +439,22 @@ def test_issue_1454():
...
@@ -439,3 +439,22 @@ def test_issue_1454():
# Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
# Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
m
.
test_gil
()
m
.
test_gil
()
m
.
test_gil_from_thread
()
m
.
test_gil_from_thread
()
def
test_python_override
():
def
func
():
class
Test
(
m
.
test_override_cache_helper
):
def
func
(
self
):
return
42
return
Test
()
def
func2
():
class
Test
(
m
.
test_override_cache_helper
):
pass
return
Test
()
for
_
in
range
(
1500
):
assert
m
.
test_override_cache
(
func
())
==
42
assert
m
.
test_override_cache
(
func2
())
==
0
tools/pybind11Common.cmake
View file @
93716147
...
@@ -318,13 +318,21 @@ function(_pybind11_generate_lto target prefer_thin_lto)
...
@@ -318,13 +318,21 @@ function(_pybind11_generate_lto target prefer_thin_lto)
set
(
cxx_append
";-fno-fat-lto-objects"
)
set
(
cxx_append
";-fno-fat-lto-objects"
)
endif
()
endif
()
if
(
CMAKE_CXX_COMPILER_ID MATCHES
"Clang"
AND prefer_thin_lto
)
if
(
CMAKE_SYSTEM_PROCESSOR MATCHES
"ppc64le"
OR CMAKE_SYSTEM_PROCESSOR MATCHES
"mips64"
)
set
(
NO_FLTO_ARCH TRUE
)
else
()
set
(
NO_FLTO_ARCH FALSE
)
endif
()
if
(
CMAKE_CXX_COMPILER_ID MATCHES
"Clang"
AND prefer_thin_lto
AND NOT NO_FLTO_ARCH
)
_pybind11_return_if_cxx_and_linker_flags_work
(
_pybind11_return_if_cxx_and_linker_flags_work
(
HAS_FLTO_THIN
"-flto=thin
${
cxx_append
}
"
"-flto=thin
${
linker_append
}
"
HAS_FLTO_THIN
"-flto=thin
${
cxx_append
}
"
"-flto=thin
${
linker_append
}
"
PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS
)
PYBIND11_LTO_CXX_FLAGS PYBIND11_LTO_LINKER_FLAGS
)
endif
()
endif
()
if
(
NOT HAS_FLTO_THIN
)
if
(
NOT HAS_FLTO_THIN
AND NOT NO_FLTO_ARCH
)
_pybind11_return_if_cxx_and_linker_flags_work
(
_pybind11_return_if_cxx_and_linker_flags_work
(
HAS_FLTO
"-flto
${
cxx_append
}
"
"-flto
${
linker_append
}
"
PYBIND11_LTO_CXX_FLAGS
HAS_FLTO
"-flto
${
cxx_append
}
"
"-flto
${
linker_append
}
"
PYBIND11_LTO_CXX_FLAGS
PYBIND11_LTO_LINKER_FLAGS
)
PYBIND11_LTO_LINKER_FLAGS
)
...
...
tools/pybind11Config.cmake.in
View file @
93716147
...
@@ -13,7 +13,7 @@ This module sets the following variables in your project:
...
@@ -13,7 +13,7 @@ This module sets the following variables in your project:
``pybind11_VERSION``
``pybind11_VERSION``
pybind11 version in format Major.Minor.Release
pybind11 version in format Major.Minor.Release
``pybind11_VERSION_TYPE``
``pybind11_VERSION_TYPE``
pybind11 version type (dev
,
release)
pybind11 version type (
``
dev
*`` or empty for a
release)
``pybind11_INCLUDE_DIRS``
``pybind11_INCLUDE_DIRS``
Directories where pybind11 and python headers are located.
Directories where pybind11 and python headers are located.
``pybind11_INCLUDE_DIR``
``pybind11_INCLUDE_DIR``
...
@@ -228,6 +228,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
...
@@ -228,6 +228,6 @@ include("${CMAKE_CURRENT_LIST_DIR}/pybind11Common.cmake")
if(NOT pybind11_FIND_QUIETLY)
if(NOT pybind11_FIND_QUIETLY)
message(
message(
STATUS
STATUS
"Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}
\"
${pybind11_VERSION_TYPE})"
"Found pybind11: ${pybind11_INCLUDE_DIR} (found version \"${pybind11_VERSION}${pybind11_VERSION_TYPE}
\"
)"
)
)
endif()
endif()
Prev
1
2
3
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