Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pybind11
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open
pybind11
Commits
bdfb50f3
Commit
bdfb50f3
authored
Jun 07, 2017
by
Dean Moldovan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Move tests from test_issues.cpp/py into appropriate files
parent
44e9a4e6
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
510 additions
and
632 deletions
+510
-632
tests/CMakeLists.txt
+1
-2
tests/test_copy_move.cpp
+19
-0
tests/test_copy_move.py
+10
-0
tests/test_inheritance.cpp
+20
-0
tests/test_inheritance.py
+13
-0
tests/test_issues.cpp
+0
-377
tests/test_issues.py
+0
-243
tests/test_methods_and_attributes.cpp
+16
-0
tests/test_methods_and_attributes.py
+52
-8
tests/test_modules.cpp
+43
-0
tests/test_modules.py
+7
-0
tests/test_operator_overloading.cpp
+69
-1
tests/test_operator_overloading.py
+55
-1
tests/test_python_types.cpp
+27
-0
tests/test_python_types.py
+14
-0
tests/test_sequences_and_iterators.cpp
+10
-0
tests/test_sequences_and_iterators.py
+17
-0
tests/test_smart_ptr.cpp
+29
-0
tests/test_smart_ptr.py
+12
-0
tests/test_virtual_functions.cpp
+57
-0
tests/test_virtual_functions.py
+39
-0
No files found.
tests/CMakeLists.txt
View file @
bdfb50f3
...
@@ -40,7 +40,6 @@ set(PYBIND11_TEST_FILES
...
@@ -40,7 +40,6 @@ set(PYBIND11_TEST_FILES
test_eval.cpp
test_eval.cpp
test_exceptions.cpp
test_exceptions.cpp
test_inheritance.cpp
test_inheritance.cpp
test_issues.cpp
test_kwargs_and_defaults.cpp
test_kwargs_and_defaults.cpp
test_methods_and_attributes.cpp
test_methods_and_attributes.cpp
test_modules.cpp
test_modules.cpp
...
@@ -59,7 +58,7 @@ set(PYBIND11_TEST_FILES
...
@@ -59,7 +58,7 @@ set(PYBIND11_TEST_FILES
)
)
# Invoking cmake with something like:
# Invoking cmake with something like:
# cmake -DPYBIND11_TEST_OVERRIDE="test_
issue
s.cpp;test_picking.cpp" ..
# cmake -DPYBIND11_TEST_OVERRIDE="test_
callback
s.cpp;test_picking.cpp" ..
# lets you override the tests that get compiled and run. You can restore to all tests with:
# lets you override the tests that get compiled and run. You can restore to all tests with:
# cmake -DPYBIND11_TEST_OVERRIDE= ..
# cmake -DPYBIND11_TEST_OVERRIDE= ..
if
(
PYBIND11_TEST_OVERRIDE
)
if
(
PYBIND11_TEST_OVERRIDE
)
...
...
tests/test_copy_move.cpp
View file @
bdfb50f3
...
@@ -187,4 +187,23 @@ test_initializer copy_move_policies([](py::module &m) {
...
@@ -187,4 +187,23 @@ test_initializer copy_move_policies([](py::module &m) {
static
PrivateOpNew
x
{};
static
PrivateOpNew
x
{};
return
x
;
return
x
;
},
py
::
return_value_policy
::
reference
);
},
py
::
return_value_policy
::
reference
);
// #389: rvp::move should fall-through to copy on non-movable objects
struct
MoveIssue1
{
int
v
;
MoveIssue1
(
int
v
)
:
v
{
v
}
{}
MoveIssue1
(
const
MoveIssue1
&
c
)
=
default
;
MoveIssue1
(
MoveIssue1
&&
)
=
delete
;
};
struct
MoveIssue2
{
int
v
;
MoveIssue2
(
int
v
)
:
v
{
v
}
{}
MoveIssue2
(
MoveIssue2
&&
)
=
default
;
};
py
::
class_
<
MoveIssue1
>
(
m
,
"MoveIssue1"
).
def
(
py
::
init
<
int
>
()).
def_readwrite
(
"value"
,
&
MoveIssue1
::
v
);
py
::
class_
<
MoveIssue2
>
(
m
,
"MoveIssue2"
).
def
(
py
::
init
<
int
>
()).
def_readwrite
(
"value"
,
&
MoveIssue2
::
v
);
m
.
def
(
"get_moveissue1"
,
[](
int
i
)
{
return
new
MoveIssue1
(
i
);
},
py
::
return_value_policy
::
move
);
m
.
def
(
"get_moveissue2"
,
[](
int
i
)
{
return
MoveIssue2
(
i
);
},
py
::
return_value_policy
::
move
);
});
});
tests/test_copy_move.py
View file @
bdfb50f3
...
@@ -109,3 +109,13 @@ def test_private_op_new():
...
@@ -109,3 +109,13 @@ def test_private_op_new():
assert
"the object is neither movable nor copyable"
in
str
(
excinfo
.
value
)
assert
"the object is neither movable nor copyable"
in
str
(
excinfo
.
value
)
assert
m
.
private_op_new_reference
()
.
value
==
1
assert
m
.
private_op_new_reference
()
.
value
==
1
def
test_move_fallback
():
"""#389: rvp::move should fall-through to copy on non-movable objects"""
from
pybind11_tests
import
get_moveissue1
,
get_moveissue2
m2
=
get_moveissue2
(
2
)
assert
m2
.
value
==
2
m1
=
get_moveissue1
(
1
)
assert
m1
.
value
==
1
tests/test_inheritance.cpp
View file @
bdfb50f3
...
@@ -120,4 +120,24 @@ test_initializer inheritance([](py::module &m) {
...
@@ -120,4 +120,24 @@ test_initializer inheritance([](py::module &m) {
py
::
class_
<
MismatchBase2
>
(
m
,
"MismatchBase2"
);
py
::
class_
<
MismatchBase2
>
(
m
,
"MismatchBase2"
);
py
::
class_
<
MismatchDerived2
,
std
::
shared_ptr
<
MismatchDerived2
>
,
MismatchBase2
>
(
m
,
"MismatchDerived2"
);
py
::
class_
<
MismatchDerived2
,
std
::
shared_ptr
<
MismatchDerived2
>
,
MismatchBase2
>
(
m
,
"MismatchDerived2"
);
});
});
// #511: problem with inheritance + overwritten def_static
struct
MyBase
{
static
std
::
unique_ptr
<
MyBase
>
make
()
{
return
std
::
unique_ptr
<
MyBase
>
(
new
MyBase
());
}
};
struct
MyDerived
:
MyBase
{
static
std
::
unique_ptr
<
MyDerived
>
make
()
{
return
std
::
unique_ptr
<
MyDerived
>
(
new
MyDerived
());
}
};
py
::
class_
<
MyBase
>
(
m
,
"MyBase"
)
.
def_static
(
"make"
,
&
MyBase
::
make
);
py
::
class_
<
MyDerived
,
MyBase
>
(
m
,
"MyDerived"
)
.
def_static
(
"make"
,
&
MyDerived
::
make
)
.
def_static
(
"make2"
,
&
MyDerived
::
make
);
});
});
tests/test_inheritance.py
View file @
bdfb50f3
...
@@ -76,3 +76,16 @@ def test_holder():
...
@@ -76,3 +76,16 @@ def test_holder():
assert
str
(
excinfo
.
value
)
==
(
"generic_type: type
\"
MismatchDerived2
\"
has a "
assert
str
(
excinfo
.
value
)
==
(
"generic_type: type
\"
MismatchDerived2
\"
has a "
"non-default holder type while its base "
"non-default holder type while its base "
"
\"
MismatchBase2
\"
does not"
)
"
\"
MismatchBase2
\"
does not"
)
def
test_inheritance_override_def_static
():
"""#511: problem with inheritance + overwritten def_static"""
from
pybind11_tests
import
MyBase
,
MyDerived
b
=
MyBase
.
make
()
d1
=
MyDerived
.
make2
()
d2
=
MyDerived
.
make
()
assert
isinstance
(
b
,
MyBase
)
assert
isinstance
(
d1
,
MyDerived
)
assert
isinstance
(
d2
,
MyDerived
)
tests/test_issues.cpp
deleted
100644 → 0
View file @
44e9a4e6
/*
tests/test_issues.cpp -- collection of testcases for miscellaneous issues
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"
#include <pybind11/stl.h>
#include <pybind11/operators.h>
#include <pybind11/complex.h>
#define TRACKERS(CLASS) CLASS() { print_default_created(this); } ~CLASS() { print_destroyed(this); }
struct
NestABase
{
int
value
=
-
2
;
TRACKERS
(
NestABase
)
};
struct
NestA
:
NestABase
{
int
value
=
3
;
NestA
&
operator
+=
(
int
i
)
{
value
+=
i
;
return
*
this
;
}
TRACKERS
(
NestA
)
};
struct
NestB
{
NestA
a
;
int
value
=
4
;
NestB
&
operator
-=
(
int
i
)
{
value
-=
i
;
return
*
this
;
}
TRACKERS
(
NestB
)
};
struct
NestC
{
NestB
b
;
int
value
=
5
;
NestC
&
operator
*=
(
int
i
)
{
value
*=
i
;
return
*
this
;
}
TRACKERS
(
NestC
)
};
/// #393
class
OpTest1
{};
class
OpTest2
{};
OpTest1
operator
+
(
const
OpTest1
&
,
const
OpTest1
&
)
{
py
::
print
(
"Add OpTest1 with OpTest1"
);
return
OpTest1
();
}
OpTest2
operator
+
(
const
OpTest2
&
,
const
OpTest2
&
)
{
py
::
print
(
"Add OpTest2 with OpTest2"
);
return
OpTest2
();
}
OpTest2
operator
+
(
const
OpTest2
&
,
const
OpTest1
&
)
{
py
::
print
(
"Add OpTest2 with OpTest1"
);
return
OpTest2
();
}
// #461
class
Dupe1
{
public
:
Dupe1
(
int
v
)
:
v_
{
v
}
{}
int
get_value
()
const
{
return
v_
;
}
private
:
int
v_
;
};
class
Dupe2
{};
class
Dupe3
{};
class
DupeException
:
public
std
::
runtime_error
{};
// #478
template
<
typename
T
>
class
custom_unique_ptr
{
public
:
custom_unique_ptr
()
{
print_default_created
(
this
);
}
custom_unique_ptr
(
T
*
ptr
)
:
_ptr
{
ptr
}
{
print_created
(
this
,
ptr
);
}
custom_unique_ptr
(
custom_unique_ptr
<
T
>
&&
move
)
:
_ptr
{
move
.
_ptr
}
{
move
.
_ptr
=
nullptr
;
print_move_created
(
this
);
}
custom_unique_ptr
&
operator
=
(
custom_unique_ptr
<
T
>
&&
move
)
{
print_move_assigned
(
this
);
if
(
_ptr
)
destruct_ptr
();
_ptr
=
move
.
_ptr
;
move
.
_ptr
=
nullptr
;
return
*
this
;
}
custom_unique_ptr
(
const
custom_unique_ptr
<
T
>
&
)
=
delete
;
void
operator
=
(
const
custom_unique_ptr
<
T
>
&
copy
)
=
delete
;
~
custom_unique_ptr
()
{
print_destroyed
(
this
);
if
(
_ptr
)
destruct_ptr
();
}
private
:
T
*
_ptr
=
nullptr
;
void
destruct_ptr
()
{
delete
_ptr
;
}
};
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
custom_unique_ptr
<
T
>
);
/// Issue #528: templated constructor
struct
TplConstrClass
{
template
<
typename
T
>
TplConstrClass
(
const
T
&
arg
)
:
str
{
arg
}
{}
std
::
string
str
;
bool
operator
==
(
const
TplConstrClass
&
t
)
const
{
return
t
.
str
==
str
;
}
};
namespace
std
{
template
<>
struct
hash
<
TplConstrClass
>
{
size_t
operator
()(
const
TplConstrClass
&
t
)
const
{
return
std
::
hash
<
std
::
string
>
()(
t
.
str
);
}
};
}
void
init_issues
(
py
::
module
&
m
)
{
py
::
module
m2
=
m
.
def_submodule
(
"issues"
);
// #137: const char* isn't handled properly
m2
.
def
(
"print_cchar"
,
[](
const
char
*
s
)
{
return
std
::
string
(
s
);
});
// #150: char bindings broken
m2
.
def
(
"print_char"
,
[](
char
c
)
{
return
std
::
string
(
1
,
c
);
});
// #159: virtual function dispatch has problems with similar-named functions
struct
Base
{
virtual
std
::
string
dispatch
()
const
{
/* for some reason MSVC2015 can't compile this if the function is pure virtual */
return
{};
};
};
struct
DispatchIssue
:
Base
{
virtual
std
::
string
dispatch
()
const
{
PYBIND11_OVERLOAD_PURE
(
std
::
string
,
Base
,
dispatch
,
/* no arguments */
);
}
};
py
::
class_
<
Base
,
DispatchIssue
>
(
m2
,
"DispatchIssue"
)
.
def
(
py
::
init
<>
())
.
def
(
"dispatch"
,
&
Base
::
dispatch
);
m2
.
def
(
"dispatch_issue_go"
,
[](
const
Base
*
b
)
{
return
b
->
dispatch
();
});
struct
Placeholder
{
int
i
;
Placeholder
(
int
i
)
:
i
(
i
)
{
}
};
py
::
class_
<
Placeholder
>
(
m2
,
"Placeholder"
)
.
def
(
py
::
init
<
int
>
())
.
def
(
"__repr__"
,
[](
const
Placeholder
&
p
)
{
return
"Placeholder["
+
std
::
to_string
(
p
.
i
)
+
"]"
;
});
// #181: iterator passthrough did not compile
m2
.
def
(
"iterator_passthrough"
,
[](
py
::
iterator
s
)
->
py
::
iterator
{
return
py
::
make_iterator
(
std
::
begin
(
s
),
std
::
end
(
s
));
});
// #187: issue involving std::shared_ptr<> return value policy & garbage collection
struct
ElementBase
{
virtual
void
foo
()
{
}
/* Force creation of virtual table */
};
struct
ElementA
:
ElementBase
{
ElementA
(
int
v
)
:
v
(
v
)
{
}
int
value
()
{
return
v
;
}
int
v
;
};
struct
ElementList
{
void
add
(
std
::
shared_ptr
<
ElementBase
>
e
)
{
l
.
push_back
(
e
);
}
std
::
vector
<
std
::
shared_ptr
<
ElementBase
>>
l
;
};
py
::
class_
<
ElementBase
,
std
::
shared_ptr
<
ElementBase
>>
(
m2
,
"ElementBase"
);
py
::
class_
<
ElementA
,
ElementBase
,
std
::
shared_ptr
<
ElementA
>>
(
m2
,
"ElementA"
)
.
def
(
py
::
init
<
int
>
())
.
def
(
"value"
,
&
ElementA
::
value
);
py
::
class_
<
ElementList
,
std
::
shared_ptr
<
ElementList
>>
(
m2
,
"ElementList"
)
.
def
(
py
::
init
<>
())
.
def
(
"add"
,
&
ElementList
::
add
)
.
def
(
"get"
,
[](
ElementList
&
el
)
{
py
::
list
list
;
for
(
auto
&
e
:
el
.
l
)
list
.
append
(
py
::
cast
(
e
));
return
list
;
});
// (no id): should not be able to pass 'None' to a reference argument
m2
.
def
(
"get_element"
,
[](
ElementA
&
el
)
{
return
el
.
value
();
});
// (no id): don't cast doubles to ints
m2
.
def
(
"expect_float"
,
[](
float
f
)
{
return
f
;
});
m2
.
def
(
"expect_int"
,
[](
int
i
)
{
return
i
;
});
try
{
py
::
class_
<
Placeholder
>
(
m2
,
"Placeholder"
);
throw
std
::
logic_error
(
"Expected an exception!"
);
}
catch
(
std
::
runtime_error
&
)
{
/* All good */
}
// Issue #283: __str__ called on uninitialized instance when constructor arguments invalid
class
StrIssue
{
public
:
StrIssue
(
int
i
)
:
val
{
i
}
{}
StrIssue
()
:
StrIssue
(
-
1
)
{}
int
value
()
const
{
return
val
;
}
private
:
int
val
;
};
py
::
class_
<
StrIssue
>
si
(
m2
,
"StrIssue"
);
si
.
def
(
py
::
init
<
int
>
())
.
def
(
py
::
init
<>
())
.
def
(
"__str__"
,
[](
const
StrIssue
&
si
)
{
return
"StrIssue["
+
std
::
to_string
(
si
.
value
())
+
"]"
;
})
;
// Issue #328: first member in a class can't be used in operators
py
::
class_
<
NestABase
>
(
m2
,
"NestABase"
).
def
(
py
::
init
<>
()).
def_readwrite
(
"value"
,
&
NestABase
::
value
);
py
::
class_
<
NestA
>
(
m2
,
"NestA"
).
def
(
py
::
init
<>
()).
def
(
py
::
self
+=
int
())
.
def
(
"as_base"
,
[](
NestA
&
a
)
->
NestABase
&
{
return
(
NestABase
&
)
a
;
},
py
::
return_value_policy
::
reference_internal
);
py
::
class_
<
NestB
>
(
m2
,
"NestB"
).
def
(
py
::
init
<>
()).
def
(
py
::
self
-=
int
()).
def_readwrite
(
"a"
,
&
NestB
::
a
);
py
::
class_
<
NestC
>
(
m2
,
"NestC"
).
def
(
py
::
init
<>
()).
def
(
py
::
self
*=
int
()).
def_readwrite
(
"b"
,
&
NestC
::
b
);
m2
.
def
(
"get_NestA"
,
[](
const
NestA
&
a
)
{
return
a
.
value
;
});
m2
.
def
(
"get_NestB"
,
[](
const
NestB
&
b
)
{
return
b
.
value
;
});
m2
.
def
(
"get_NestC"
,
[](
const
NestC
&
c
)
{
return
c
.
value
;
});
// Issue 389: r_v_p::move should fall-through to copy on non-movable objects
class
MoveIssue1
{
public
:
MoveIssue1
(
int
v
)
:
v
{
v
}
{}
MoveIssue1
(
const
MoveIssue1
&
c
)
{
v
=
c
.
v
;
}
MoveIssue1
(
MoveIssue1
&&
)
=
delete
;
int
v
;
};
class
MoveIssue2
{
public
:
MoveIssue2
(
int
v
)
:
v
{
v
}
{}
MoveIssue2
(
MoveIssue2
&&
)
=
default
;
int
v
;
};
py
::
class_
<
MoveIssue1
>
(
m2
,
"MoveIssue1"
).
def
(
py
::
init
<
int
>
()).
def_readwrite
(
"value"
,
&
MoveIssue1
::
v
);
py
::
class_
<
MoveIssue2
>
(
m2
,
"MoveIssue2"
).
def
(
py
::
init
<
int
>
()).
def_readwrite
(
"value"
,
&
MoveIssue2
::
v
);
m2
.
def
(
"get_moveissue1"
,
[](
int
i
)
->
MoveIssue1
*
{
return
new
MoveIssue1
(
i
);
},
py
::
return_value_policy
::
move
);
m2
.
def
(
"get_moveissue2"
,
[](
int
i
)
{
return
MoveIssue2
(
i
);
},
py
::
return_value_policy
::
move
);
// Issues 392/397: overridding reference-returning functions
class
OverrideTest
{
public
:
struct
A
{
std
::
string
value
=
"hi"
;
};
std
::
string
v
;
A
a
;
explicit
OverrideTest
(
const
std
::
string
&
v
)
:
v
{
v
}
{}
virtual
std
::
string
str_value
()
{
return
v
;
}
virtual
std
::
string
&
str_ref
()
{
return
v
;
}
virtual
A
A_value
()
{
return
a
;
}
virtual
A
&
A_ref
()
{
return
a
;
}
};
class
PyOverrideTest
:
public
OverrideTest
{
public
:
using
OverrideTest
::
OverrideTest
;
std
::
string
str_value
()
override
{
PYBIND11_OVERLOAD
(
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); }
// But we can work around it like this:
private:
std
::
string
_tmp
;
std
::
string
str_ref_helper
()
{
PYBIND11_OVERLOAD
(
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
);
}
};
py
::
class_
<
OverrideTest
::
A
>
(
m2
,
"OverrideTest_A"
)
.
def_readwrite
(
"value"
,
&
OverrideTest
::
A
::
value
);
py
::
class_
<
OverrideTest
,
PyOverrideTest
>
(
m2
,
"OverrideTest"
)
.
def
(
py
::
init
<
const
std
::
string
&>
())
.
def
(
"str_value"
,
&
OverrideTest
::
str_value
)
// .def("str_ref", &OverrideTest::str_ref)
.
def
(
"A_value"
,
&
OverrideTest
::
A_value
)
.
def
(
"A_ref"
,
&
OverrideTest
::
A_ref
);
/// Issue 393: need to return NotSupported to ensure correct arithmetic operator behavior
py
::
class_
<
OpTest1
>
(
m2
,
"OpTest1"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
+
py
::
self
);
py
::
class_
<
OpTest2
>
(
m2
,
"OpTest2"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
+
py
::
self
)
.
def
(
"__add__"
,
[](
const
OpTest2
&
c2
,
const
OpTest1
&
c1
)
{
return
c2
+
c1
;
})
.
def
(
"__radd__"
,
[](
const
OpTest2
&
c2
,
const
OpTest1
&
c1
)
{
return
c2
+
c1
;
});
// Issue 388: Can't make iterators via make_iterator() with different r/v policies
static
std
::
vector
<
int
>
list
=
{
1
,
2
,
3
};
m2
.
def
(
"make_iterator_1"
,
[]()
{
return
py
::
make_iterator
<
py
::
return_value_policy
::
copy
>
(
list
);
});
m2
.
def
(
"make_iterator_2"
,
[]()
{
return
py
::
make_iterator
<
py
::
return_value_policy
::
automatic
>
(
list
);
});
static
std
::
vector
<
std
::
string
>
nothrows
;
// Issue 461: registering two things with the same name:
py
::
class_
<
Dupe1
>
(
m2
,
"Dupe1"
)
.
def
(
"get_value"
,
&
Dupe1
::
get_value
)
;
m2
.
def
(
"dupe1_factory"
,
[](
int
v
)
{
return
new
Dupe1
(
v
);
});
py
::
class_
<
Dupe2
>
(
m2
,
"Dupe2"
);
py
::
exception
<
DupeException
>
(
m2
,
"DupeException"
);
try
{
m2
.
def
(
"Dupe1"
,
[](
int
v
)
{
return
new
Dupe1
(
v
);
});
nothrows
.
emplace_back
(
"Dupe1"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
py
::
class_
<
Dupe3
>
(
m2
,
"dupe1_factory"
);
nothrows
.
emplace_back
(
"dupe1_factory"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
py
::
exception
<
Dupe3
>
(
m2
,
"Dupe2"
);
nothrows
.
emplace_back
(
"Dupe2"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
m2
.
def
(
"DupeException"
,
[]()
{
return
30
;
});
nothrows
.
emplace_back
(
"DupeException1"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
py
::
class_
<
DupeException
>
(
m2
,
"DupeException"
);
nothrows
.
emplace_back
(
"DupeException2"
);
}
catch
(
std
::
runtime_error
&
)
{}
m2
.
def
(
"dupe_exception_failures"
,
[]()
{
py
::
list
l
;
for
(
auto
&
e
:
nothrows
)
l
.
append
(
py
::
cast
(
e
));
return
l
;
});
/// Issue #471: shared pointer instance not dellocated
class
SharedChild
:
public
std
::
enable_shared_from_this
<
SharedChild
>
{
public
:
SharedChild
()
{
print_created
(
this
);
}
~
SharedChild
()
{
print_destroyed
(
this
);
}
};
class
SharedParent
{
public
:
SharedParent
()
:
child
(
std
::
make_shared
<
SharedChild
>
())
{
}
const
SharedChild
&
get_child
()
const
{
return
*
child
;
}
private
:
std
::
shared_ptr
<
SharedChild
>
child
;
};
py
::
class_
<
SharedChild
,
std
::
shared_ptr
<
SharedChild
>>
(
m
,
"SharedChild"
);
py
::
class_
<
SharedParent
,
std
::
shared_ptr
<
SharedParent
>>
(
m
,
"SharedParent"
)
.
def
(
py
::
init
<>
())
.
def
(
"get_child"
,
&
SharedParent
::
get_child
,
py
::
return_value_policy
::
reference
);
/// Issue/PR #478: unique ptrs constructed and freed without destruction
class
SpecialHolderObj
{
public
:
int
val
=
0
;
SpecialHolderObj
*
ch
=
nullptr
;
SpecialHolderObj
(
int
v
,
bool
make_child
=
true
)
:
val
{
v
},
ch
{
make_child
?
new
SpecialHolderObj
(
val
+
1
,
false
)
:
nullptr
}
{
print_created
(
this
,
val
);
}
~
SpecialHolderObj
()
{
delete
ch
;
print_destroyed
(
this
);
}
SpecialHolderObj
*
child
()
{
return
ch
;
}
};
py
::
class_
<
SpecialHolderObj
,
custom_unique_ptr
<
SpecialHolderObj
>>
(
m
,
"SpecialHolderObj"
)
.
def
(
py
::
init
<
int
>
())
.
def
(
"child"
,
&
SpecialHolderObj
::
child
,
pybind11
::
return_value_policy
::
reference_internal
)
.
def_readwrite
(
"val"
,
&
SpecialHolderObj
::
val
)
.
def_static
(
"holder_cstats"
,
&
ConstructorStats
::
get
<
custom_unique_ptr
<
SpecialHolderObj
>>
,
py
::
return_value_policy
::
reference
);
/// Issue #484: number conversion generates unhandled exceptions
m2
.
def
(
"test_complex"
,
[](
float
x
)
{
py
::
print
(
"{}"
_s
.
format
(
x
));
});
m2
.
def
(
"test_complex"
,
[](
std
::
complex
<
float
>
x
)
{
py
::
print
(
"({}, {})"
_s
.
format
(
x
.
real
(),
x
.
imag
()));
});
/// Issue #511: problem with inheritance + overwritten def_static
struct
MyBase
{
static
std
::
unique_ptr
<
MyBase
>
make
()
{
return
std
::
unique_ptr
<
MyBase
>
(
new
MyBase
());
}
};
struct
MyDerived
:
MyBase
{
static
std
::
unique_ptr
<
MyDerived
>
make
()
{
return
std
::
unique_ptr
<
MyDerived
>
(
new
MyDerived
());
}
};
py
::
class_
<
MyBase
>
(
m2
,
"MyBase"
)
.
def_static
(
"make"
,
&
MyBase
::
make
);
py
::
class_
<
MyDerived
,
MyBase
>
(
m2
,
"MyDerived"
)
.
def_static
(
"make"
,
&
MyDerived
::
make
)
.
def_static
(
"make2"
,
&
MyDerived
::
make
);
py
::
dict
d
;
std
::
string
bar
=
"bar"
;
d
[
"str"
]
=
bar
;
d
[
"num"
]
=
3.7
;
/// Issue #528: templated constructor
m2
.
def
(
"tpl_constr_vector"
,
[](
std
::
vector
<
TplConstrClass
>
&
)
{});
m2
.
def
(
"tpl_constr_map"
,
[](
std
::
unordered_map
<
TplConstrClass
,
TplConstrClass
>
&
)
{});
m2
.
def
(
"tpl_constr_set"
,
[](
std
::
unordered_set
<
TplConstrClass
>
&
)
{});
#if defined(PYBIND11_HAS_OPTIONAL)
m2
.
def
(
"tpl_constr_optional"
,
[](
std
::
optional
<
TplConstrClass
>
&
)
{});
#elif defined(PYBIND11_HAS_EXP_OPTIONAL)
m2
.
def
(
"tpl_constr_optional"
,
[](
std
::
experimental
::
optional
<
TplConstrClass
>
&
)
{});
#endif
}
// MSVC workaround: trying to use a lambda here crashes MSVC
test_initializer
issues
(
&
init_issues
);
tests/test_issues.py
deleted
100644 → 0
View file @
44e9a4e6
import
pytest
from
pybind11_tests
import
ConstructorStats
def
test_regressions
():
from
pybind11_tests.issues
import
print_cchar
,
print_char
# #137: const char* isn't handled properly
assert
print_cchar
(
"const char *"
)
==
"const char *"
# #150: char bindings broken
assert
print_char
(
"c"
)
==
"c"
def
test_dispatch_issue
(
msg
):
"""#159: virtual function dispatch has problems with similar-named functions"""
from
pybind11_tests.issues
import
DispatchIssue
,
dispatch_issue_go
class
PyClass1
(
DispatchIssue
):
def
dispatch
(
self
):
return
"Yay.."
class
PyClass2
(
DispatchIssue
):
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"'
p
=
PyClass1
()
return
dispatch_issue_go
(
p
)
b
=
PyClass2
()
assert
dispatch_issue_go
(
b
)
==
"Yay.."
def
test_iterator_passthrough
():
"""#181: iterator passthrough did not compile"""
from
pybind11_tests.issues
import
iterator_passthrough
assert
list
(
iterator_passthrough
(
iter
([
3
,
5
,
7
,
9
,
11
,
13
,
15
])))
==
[
3
,
5
,
7
,
9
,
11
,
13
,
15
]
def
test_shared_ptr_gc
():
"""// #187: issue involving std::shared_ptr<> return value policy & garbage collection"""
from
pybind11_tests.issues
import
ElementList
,
ElementA
el
=
ElementList
()
for
i
in
range
(
10
):
el
.
add
(
ElementA
(
i
))
pytest
.
gc_collect
()
for
i
,
v
in
enumerate
(
el
.
get
()):
assert
i
==
v
.
value
()
def
test_no_id
(
msg
):
from
pybind11_tests.issues
import
get_element
,
expect_float
,
expect_int
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
get_element
(
None
)
assert
msg
(
excinfo
.
value
)
==
"""
get_element(): incompatible function arguments. The following argument types are supported:
1. (arg0: m.issues.ElementA) -> int
Invoked with: None
"""
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
expect_int
(
5.2
)
assert
msg
(
excinfo
.
value
)
==
"""
expect_int(): incompatible function arguments. The following argument types are supported:
1. (arg0: int) -> int
Invoked with: 5.2
"""
assert
expect_float
(
12
)
==
12
def
test_str_issue
(
msg
):
"""Issue #283: __str__ called on uninitialized instance when constructor arguments invalid"""
from
pybind11_tests.issues
import
StrIssue
assert
str
(
StrIssue
(
3
))
==
"StrIssue[3]"
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
str
(
StrIssue
(
"no"
,
"such"
,
"constructor"
))
assert
msg
(
excinfo
.
value
)
==
"""
__init__(): incompatible constructor arguments. The following argument types are supported:
1. m.issues.StrIssue(arg0: int)
2. m.issues.StrIssue()
Invoked with: 'no', 'such', 'constructor'
"""
def
test_nested
():
""" #328: first member in a class can't be used in operators"""
from
pybind11_tests.issues
import
NestA
,
NestB
,
NestC
,
get_NestA
,
get_NestB
,
get_NestC
a
=
NestA
()
b
=
NestB
()
c
=
NestC
()
a
+=
10
assert
get_NestA
(
a
)
==
13
b
.
a
+=
100
assert
get_NestA
(
b
.
a
)
==
103
c
.
b
.
a
+=
1000
assert
get_NestA
(
c
.
b
.
a
)
==
1003
b
-=
1
assert
get_NestB
(
b
)
==
3
c
.
b
-=
3
assert
get_NestB
(
c
.
b
)
==
1
c
*=
7
assert
get_NestC
(
c
)
==
35
abase
=
a
.
as_base
()
assert
abase
.
value
==
-
2
a
.
as_base
()
.
value
+=
44
assert
abase
.
value
==
42
assert
c
.
b
.
a
.
as_base
()
.
value
==
-
2
c
.
b
.
a
.
as_base
()
.
value
+=
44
assert
c
.
b
.
a
.
as_base
()
.
value
==
42
del
c
pytest
.
gc_collect
()
del
a
# Should't delete while abase is still alive
pytest
.
gc_collect
()
assert
abase
.
value
==
42
del
abase
,
b
pytest
.
gc_collect
()
def
test_move_fallback
():
from
pybind11_tests.issues
import
get_moveissue1
,
get_moveissue2
m2
=
get_moveissue2
(
2
)
assert
m2
.
value
==
2
m1
=
get_moveissue1
(
1
)
assert
m1
.
value
==
1
def
test_override_ref
():
from
pybind11_tests.issues
import
OverrideTest
o
=
OverrideTest
(
"asdf"
)
# Not allowed (see associated .cpp comment)
# i = o.str_ref()
# assert o.str_ref() == "asdf"
assert
o
.
str_value
()
==
"asdf"
assert
o
.
A_value
()
.
value
==
"hi"
a
=
o
.
A_ref
()
assert
a
.
value
==
"hi"
a
.
value
=
"bye"
assert
a
.
value
==
"bye"
def
test_operators_notimplemented
(
capture
):
from
pybind11_tests.issues
import
OpTest1
,
OpTest2
with
capture
:
c1
,
c2
=
OpTest1
(),
OpTest2
()
c1
+
c1
c2
+
c2
c2
+
c1
c1
+
c2
assert
capture
==
"""
Add OpTest1 with OpTest1
Add OpTest2 with OpTest2
Add OpTest2 with OpTest1
Add OpTest2 with OpTest1
"""
def
test_iterator_rvpolicy
():
""" Issue 388: Can't make iterators via make_iterator() with different r/v policies """
from
pybind11_tests.issues
import
make_iterator_1
from
pybind11_tests.issues
import
make_iterator_2
assert
list
(
make_iterator_1
())
==
[
1
,
2
,
3
]
assert
list
(
make_iterator_2
())
==
[
1
,
2
,
3
]
assert
not
isinstance
(
make_iterator_1
(),
type
(
make_iterator_2
()))
def
test_dupe_assignment
():
""" Issue 461: overwriting a class with a function """
from
pybind11_tests.issues
import
dupe_exception_failures
assert
dupe_exception_failures
()
==
[]
def
test_enable_shared_from_this_with_reference_rvp
():
""" Issue #471: shared pointer instance not dellocated """
from
pybind11_tests
import
SharedParent
,
SharedChild
parent
=
SharedParent
()
child
=
parent
.
get_child
()
cstats
=
ConstructorStats
.
get
(
SharedChild
)
assert
cstats
.
alive
()
==
1
del
child
,
parent
assert
cstats
.
alive
()
==
0
def
test_non_destructed_holders
():
""" Issue #478: unique ptrs constructed and freed without destruction """
from
pybind11_tests
import
SpecialHolderObj
a
=
SpecialHolderObj
(
123
)
b
=
a
.
child
()
assert
a
.
val
==
123
assert
b
.
val
==
124
cstats
=
SpecialHolderObj
.
holder_cstats
()
assert
cstats
.
alive
()
==
1
del
b
assert
cstats
.
alive
()
==
1
del
a
assert
cstats
.
alive
()
==
0
def
test_complex_cast
(
capture
):
""" Issue #484: number conversion generates unhandled exceptions """
from
pybind11_tests.issues
import
test_complex
with
capture
:
test_complex
(
1
)
test_complex
(
2
j
)
assert
capture
==
"""
1.0
(0.0, 2.0)
"""
def
test_inheritance_override_def_static
():
from
pybind11_tests.issues
import
MyBase
,
MyDerived
b
=
MyBase
.
make
()
d1
=
MyDerived
.
make2
()
d2
=
MyDerived
.
make
()
assert
isinstance
(
b
,
MyBase
)
assert
isinstance
(
d1
,
MyDerived
)
assert
isinstance
(
d2
,
MyDerived
)
tests/test_methods_and_attributes.cpp
View file @
bdfb50f3
...
@@ -170,6 +170,13 @@ int none3(std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; }
...
@@ -170,6 +170,13 @@ int none3(std::shared_ptr<NoneTester> &obj) { return obj ? obj->answer : -1; }
int
none4
(
std
::
shared_ptr
<
NoneTester
>
*
obj
)
{
return
obj
&&
*
obj
?
(
*
obj
)
->
answer
:
-
1
;
}
int
none4
(
std
::
shared_ptr
<
NoneTester
>
*
obj
)
{
return
obj
&&
*
obj
?
(
*
obj
)
->
answer
:
-
1
;
}
int
none5
(
std
::
shared_ptr
<
NoneTester
>
obj
)
{
return
obj
?
obj
->
answer
:
-
1
;
}
int
none5
(
std
::
shared_ptr
<
NoneTester
>
obj
)
{
return
obj
?
obj
->
answer
:
-
1
;
}
struct
StrIssue
{
int
val
=
-
1
;
StrIssue
()
=
default
;
StrIssue
(
int
i
)
:
val
{
i
}
{}
};
test_initializer
methods_and_attributes
([](
py
::
module
&
m
)
{
test_initializer
methods_and_attributes
([](
py
::
module
&
m
)
{
py
::
class_
<
ExampleMandA
>
emna
(
m
,
"ExampleMandA"
);
py
::
class_
<
ExampleMandA
>
emna
(
m
,
"ExampleMandA"
);
emna
.
def
(
py
::
init
<>
())
emna
.
def
(
py
::
init
<>
())
...
@@ -315,6 +322,8 @@ test_initializer methods_and_attributes([](py::module &m) {
...
@@ -315,6 +322,8 @@ test_initializer methods_and_attributes([](py::module &m) {
m
.
def
(
"floats_preferred"
,
[](
double
f
)
{
return
0.5
*
f
;
},
py
::
arg
(
"f"
));
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
(
"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
());
/// Issue/PR #648: bad arg default debugging output
/// Issue/PR #648: bad arg default debugging output
#if !defined(NDEBUG)
#if !defined(NDEBUG)
...
@@ -344,4 +353,11 @@ test_initializer methods_and_attributes([](py::module &m) {
...
@@ -344,4 +353,11 @@ test_initializer methods_and_attributes([](py::module &m) {
m
.
def
(
"ok_none4"
,
&
none4
,
py
::
arg
().
none
(
true
));
m
.
def
(
"ok_none4"
,
&
none4
,
py
::
arg
().
none
(
true
));
m
.
def
(
"ok_none5"
,
&
none5
);
m
.
def
(
"ok_none5"
,
&
none5
);
// Issue #283: __str__ called on uninitialized instance when constructor arguments invalid
py
::
class_
<
StrIssue
>
(
m
,
"StrIssue"
)
.
def
(
py
::
init
<
int
>
())
.
def
(
py
::
init
<>
())
.
def
(
"__str__"
,
[](
const
StrIssue
&
si
)
{
return
"StrIssue["
+
std
::
to_string
(
si
.
val
)
+
"]"
;
}
);
});
});
tests/test_methods_and_attributes.py
View file @
bdfb50f3
...
@@ -304,9 +304,9 @@ def test_cyclic_gc():
...
@@ -304,9 +304,9 @@ def test_cyclic_gc():
def
test_noconvert_args
(
msg
):
def
test_noconvert_args
(
msg
):
from
pybind11_tests
import
ArgInspector
,
arg_inspect_func
,
floats_only
,
floats_preferred
import
pybind11_tests
as
m
a
=
ArgInspector
()
a
=
m
.
ArgInspector
()
assert
msg
(
a
.
f
(
"hi"
))
==
"""
assert
msg
(
a
.
f
(
"hi"
))
==
"""
loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
loading ArgInspector1 argument WITH conversion allowed. Argument value = hi
"""
"""
...
@@ -330,15 +330,15 @@ def test_noconvert_args(msg):
...
@@ -330,15 +330,15 @@ def test_noconvert_args(msg):
"""
"""
assert
(
a
.
h
(
"arg 1"
)
==
assert
(
a
.
h
(
"arg 1"
)
==
"loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1"
)
"loading ArgInspector2 argument WITHOUT conversion allowed. Argument value = arg 1"
)
assert
msg
(
arg_inspect_func
(
"A1"
,
"A2"
))
==
"""
assert
msg
(
m
.
arg_inspect_func
(
"A1"
,
"A2"
))
==
"""
loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
loading ArgInspector2 argument WITH conversion allowed. Argument value = A1
loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
loading ArgInspector1 argument WITHOUT conversion allowed. Argument value = A2
"""
"""
assert
floats_preferred
(
4
)
==
2.0
assert
m
.
floats_preferred
(
4
)
==
2.0
assert
floats_only
(
4.0
)
==
2.0
assert
m
.
floats_only
(
4.0
)
==
2.0
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
floats_only
(
4
)
m
.
floats_only
(
4
)
assert
msg
(
excinfo
.
value
)
==
"""
assert
msg
(
excinfo
.
value
)
==
"""
floats_only(): incompatible function arguments. The following argument types are supported:
floats_only(): incompatible function arguments. The following argument types are supported:
1. (f: float) -> float
1. (f: float) -> float
...
@@ -346,6 +346,27 @@ def test_noconvert_args(msg):
...
@@ -346,6 +346,27 @@ def test_noconvert_args(msg):
Invoked with: 4
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
):
def
test_bad_arg_default
(
msg
):
from
pybind11_tests
import
debug_enabled
,
bad_arg_def_named
,
bad_arg_def_unnamed
from
pybind11_tests
import
debug_enabled
,
bad_arg_def_named
,
bad_arg_def_unnamed
...
@@ -371,7 +392,7 @@ def test_bad_arg_default(msg):
...
@@ -371,7 +392,7 @@ def test_bad_arg_default(msg):
)
)
def
test_accepts_none
():
def
test_accepts_none
(
msg
):
from
pybind11_tests
import
(
NoneTester
,
from
pybind11_tests
import
(
NoneTester
,
no_none1
,
no_none2
,
no_none3
,
no_none4
,
no_none5
,
no_none1
,
no_none2
,
no_none3
,
no_none4
,
no_none5
,
ok_none1
,
ok_none2
,
ok_none3
,
ok_none4
,
ok_none5
)
ok_none1
,
ok_none2
,
ok_none3
,
ok_none4
,
ok_none5
)
...
@@ -407,9 +428,32 @@ def test_accepts_none():
...
@@ -407,9 +428,32 @@ def test_accepts_none():
# The first one still raises because you can't pass None as a lvalue reference arg:
# The first one still raises because you can't pass None as a lvalue reference arg:
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
assert
ok_none1
(
None
)
==
-
1
assert
ok_none1
(
None
)
==
-
1
assert
"incompatible function arguments"
in
str
(
excinfo
.
value
)
assert
msg
(
excinfo
.
value
)
==
"""
ok_none1(): incompatible function arguments. The following argument types are supported:
1. (arg0: m.NoneTester) -> int
Invoked with: None
"""
# The rest take the argument as pointer or holder, and accept None:
# The rest take the argument as pointer or holder, and accept None:
assert
ok_none2
(
None
)
==
-
1
assert
ok_none2
(
None
)
==
-
1
assert
ok_none3
(
None
)
==
-
1
assert
ok_none3
(
None
)
==
-
1
assert
ok_none4
(
None
)
==
-
1
assert
ok_none4
(
None
)
==
-
1
assert
ok_none5
(
None
)
==
-
1
assert
ok_none5
(
None
)
==
-
1
def
test_str_issue
(
msg
):
"""#283: __str__ called on uninitialized instance when constructor arguments invalid"""
from
pybind11_tests
import
StrIssue
assert
str
(
StrIssue
(
3
))
==
"StrIssue[3]"
with
pytest
.
raises
(
TypeError
)
as
excinfo
:
str
(
StrIssue
(
"no"
,
"such"
,
"constructor"
))
assert
msg
(
excinfo
.
value
)
==
"""
__init__(): incompatible constructor arguments. The following argument types are supported:
1. m.StrIssue(arg0: int)
2. m.StrIssue()
Invoked with: 'no', 'such', 'constructor'
"""
tests/test_modules.cpp
View file @
bdfb50f3
...
@@ -55,4 +55,47 @@ test_initializer modules([](py::module &m) {
...
@@ -55,4 +55,47 @@ test_initializer modules([](py::module &m) {
.
def_readwrite
(
"a2"
,
&
B
::
a2
);
.
def_readwrite
(
"a2"
,
&
B
::
a2
);
m
.
attr
(
"OD"
)
=
py
::
module
::
import
(
"collections"
).
attr
(
"OrderedDict"
);
m
.
attr
(
"OD"
)
=
py
::
module
::
import
(
"collections"
).
attr
(
"OrderedDict"
);
// Registering two things with the same name
m
.
def
(
"duplicate_registration"
,
[]()
{
class
Dupe1
{
};
class
Dupe2
{
};
class
Dupe3
{
};
class
DupeException
{
};
auto
dm
=
py
::
module
(
"dummy"
);
auto
failures
=
py
::
list
();
py
::
class_
<
Dupe1
>
(
dm
,
"Dupe1"
);
py
::
class_
<
Dupe2
>
(
dm
,
"Dupe2"
);
dm
.
def
(
"dupe1_factory"
,
[]()
{
return
Dupe1
();
});
py
::
exception
<
DupeException
>
(
dm
,
"DupeException"
);
try
{
py
::
class_
<
Dupe1
>
(
dm
,
"Dupe1"
);
failures
.
append
(
"Dupe1 class"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
dm
.
def
(
"Dupe1"
,
[]()
{
return
Dupe1
();
});
failures
.
append
(
"Dupe1 function"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
py
::
class_
<
Dupe3
>
(
dm
,
"dupe1_factory"
);
failures
.
append
(
"dupe1_factory"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
py
::
exception
<
Dupe3
>
(
dm
,
"Dupe2"
);
failures
.
append
(
"Dupe2"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
dm
.
def
(
"DupeException"
,
[]()
{
return
30
;
});
failures
.
append
(
"DupeException1"
);
}
catch
(
std
::
runtime_error
&
)
{}
try
{
py
::
class_
<
DupeException
>
(
dm
,
"DupeException"
);
failures
.
append
(
"DupeException2"
);
}
catch
(
std
::
runtime_error
&
)
{}
return
failures
;
});
});
});
tests/test_modules.py
View file @
bdfb50f3
...
@@ -61,3 +61,10 @@ def test_pydoc():
...
@@ -61,3 +61,10 @@ def test_pydoc():
assert
pybind11_tests
.
__doc__
==
"pybind11 test module"
assert
pybind11_tests
.
__doc__
==
"pybind11 test module"
assert
pydoc
.
text
.
docmodule
(
pybind11_tests
)
assert
pydoc
.
text
.
docmodule
(
pybind11_tests
)
def
test_duplicate_registration
():
"""Registering two things with the same name"""
from
pybind11_tests
import
duplicate_registration
assert
duplicate_registration
()
==
[]
tests/test_operator_overloading.cpp
View file @
bdfb50f3
...
@@ -56,7 +56,38 @@ private:
...
@@ -56,7 +56,38 @@ private:
float
x
,
y
;
float
x
,
y
;
};
};
test_initializer
operator_overloading
([](
py
::
module
&
m
)
{
class
C1
{
};
class
C2
{
};
int
operator
+
(
const
C1
&
,
const
C1
&
)
{
return
11
;
}
int
operator
+
(
const
C2
&
,
const
C2
&
)
{
return
22
;
}
int
operator
+
(
const
C2
&
,
const
C1
&
)
{
return
21
;
}
int
operator
+
(
const
C1
&
,
const
C2
&
)
{
return
12
;
}
struct
NestABase
{
int
value
=
-
2
;
};
struct
NestA
:
NestABase
{
int
value
=
3
;
NestA
&
operator
+=
(
int
i
)
{
value
+=
i
;
return
*
this
;
}
};
struct
NestB
{
NestA
a
;
int
value
=
4
;
NestB
&
operator
-=
(
int
i
)
{
value
-=
i
;
return
*
this
;
}
};
struct
NestC
{
NestB
b
;
int
value
=
5
;
NestC
&
operator
*=
(
int
i
)
{
value
*=
i
;
return
*
this
;
}
};
test_initializer
operator_overloading
([](
py
::
module
&
pm
)
{
auto
m
=
pm
.
def_submodule
(
"operators"
);
py
::
class_
<
Vector2
>
(
m
,
"Vector2"
)
py
::
class_
<
Vector2
>
(
m
,
"Vector2"
)
.
def
(
py
::
init
<
float
,
float
>
())
.
def
(
py
::
init
<
float
,
float
>
())
.
def
(
py
::
self
+
py
::
self
)
.
def
(
py
::
self
+
py
::
self
)
...
@@ -81,4 +112,41 @@ test_initializer operator_overloading([](py::module &m) {
...
@@ -81,4 +112,41 @@ test_initializer operator_overloading([](py::module &m) {
;
;
m
.
attr
(
"Vector"
)
=
m
.
attr
(
"Vector2"
);
m
.
attr
(
"Vector"
)
=
m
.
attr
(
"Vector2"
);
// #393: need to return NotSupported to ensure correct arithmetic operator behavior
py
::
class_
<
C1
>
(
m
,
"C1"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
+
py
::
self
);
py
::
class_
<
C2
>
(
m
,
"C2"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
+
py
::
self
)
.
def
(
"__add__"
,
[](
const
C2
&
c2
,
const
C1
&
c1
)
{
return
c2
+
c1
;
})
.
def
(
"__radd__"
,
[](
const
C2
&
c2
,
const
C1
&
c1
)
{
return
c1
+
c2
;
});
// #328: first member in a class can't be used in operators
py
::
class_
<
NestABase
>
(
m
,
"NestABase"
)
.
def
(
py
::
init
<>
())
.
def_readwrite
(
"value"
,
&
NestABase
::
value
);
py
::
class_
<
NestA
>
(
m
,
"NestA"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
+=
int
())
.
def
(
"as_base"
,
[](
NestA
&
a
)
->
NestABase
&
{
return
(
NestABase
&
)
a
;
},
py
::
return_value_policy
::
reference_internal
);
py
::
class_
<
NestB
>
(
m
,
"NestB"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
-=
int
())
.
def_readwrite
(
"a"
,
&
NestB
::
a
);
py
::
class_
<
NestC
>
(
m
,
"NestC"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
self
*=
int
())
.
def_readwrite
(
"b"
,
&
NestC
::
b
);
m
.
def
(
"get_NestA"
,
[](
const
NestA
&
a
)
{
return
a
.
value
;
});
m
.
def
(
"get_NestB"
,
[](
const
NestB
&
b
)
{
return
b
.
value
;
});
m
.
def
(
"get_NestC"
,
[](
const
NestC
&
c
)
{
return
c
.
value
;
});
});
});
tests/test_operator_overloading.py
View file @
bdfb50f3
import
pytest
from
pybind11_tests
import
ConstructorStats
def
test_operator_overloading
():
def
test_operator_overloading
():
from
pybind11_tests
import
Vector2
,
Vector
,
ConstructorStats
from
pybind11_tests
.operators
import
Vector2
,
Vector
v1
=
Vector2
(
1
,
2
)
v1
=
Vector2
(
1
,
2
)
v2
=
Vector
(
3
,
-
1
)
v2
=
Vector
(
3
,
-
1
)
...
@@ -51,3 +55,53 @@ def test_operator_overloading():
...
@@ -51,3 +55,53 @@ def test_operator_overloading():
assert
cstats
.
move_constructions
>=
10
assert
cstats
.
move_constructions
>=
10
assert
cstats
.
copy_assignments
==
0
assert
cstats
.
copy_assignments
==
0
assert
cstats
.
move_assignments
==
0
assert
cstats
.
move_assignments
==
0
def
test_operators_notimplemented
():
"""#393: need to return NotSupported to ensure correct arithmetic operator behavior"""
from
pybind11_tests.operators
import
C1
,
C2
c1
,
c2
=
C1
(),
C2
()
assert
c1
+
c1
==
11
assert
c2
+
c2
==
22
assert
c2
+
c1
==
21
assert
c1
+
c2
==
12
def
test_nested
():
"""#328: first member in a class can't be used in operators"""
from
pybind11_tests.operators
import
NestA
,
NestB
,
NestC
,
get_NestA
,
get_NestB
,
get_NestC
a
=
NestA
()
b
=
NestB
()
c
=
NestC
()
a
+=
10
assert
get_NestA
(
a
)
==
13
b
.
a
+=
100
assert
get_NestA
(
b
.
a
)
==
103
c
.
b
.
a
+=
1000
assert
get_NestA
(
c
.
b
.
a
)
==
1003
b
-=
1
assert
get_NestB
(
b
)
==
3
c
.
b
-=
3
assert
get_NestB
(
c
.
b
)
==
1
c
*=
7
assert
get_NestC
(
c
)
==
35
abase
=
a
.
as_base
()
assert
abase
.
value
==
-
2
a
.
as_base
()
.
value
+=
44
assert
abase
.
value
==
42
assert
c
.
b
.
a
.
as_base
()
.
value
==
-
2
c
.
b
.
a
.
as_base
()
.
value
+=
44
assert
c
.
b
.
a
.
as_base
()
.
value
==
42
del
c
pytest
.
gc_collect
()
del
a
# Should't delete while abase is still alive
pytest
.
gc_collect
()
assert
abase
.
value
==
42
del
abase
,
b
pytest
.
gc_collect
()
tests/test_python_types.cpp
View file @
bdfb50f3
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
#include "pybind11_tests.h"
#include "pybind11_tests.h"
#include "constructor_stats.h"
#include "constructor_stats.h"
#include <pybind11/stl.h>
#include <pybind11/stl.h>
#include <pybind11/complex.h>
#ifdef _WIN32
#ifdef _WIN32
# include <io.h>
# include <io.h>
...
@@ -215,6 +216,17 @@ std::vector<std::reference_wrapper<IncrIntWrapper>> incr_int_wrappers() {
...
@@ -215,6 +216,17 @@ std::vector<std::reference_wrapper<IncrIntWrapper>> incr_int_wrappers() {
return
r
;
return
r
;
};
};
/// Issue #528: templated constructor
struct
TplCtorClass
{
template
<
typename
T
>
TplCtorClass
(
const
T
&
)
{
}
bool
operator
==
(
const
TplCtorClass
&
)
const
{
return
true
;
}
};
namespace
std
{
template
<>
struct
hash
<
TplCtorClass
>
{
size_t
operator
()(
const
TplCtorClass
&
)
const
{
return
0
;
}
};
}
test_initializer
python_types
([](
py
::
module
&
m
)
{
test_initializer
python_types
([](
py
::
module
&
m
)
{
/* No constructor is explicitly defined below. An exception is raised when
/* No constructor is explicitly defined below. An exception is raised when
trying to construct it directly from Python */
trying to construct it directly from Python */
...
@@ -501,6 +513,8 @@ test_initializer python_types([](py::module &m) {
...
@@ -501,6 +513,8 @@ test_initializer python_types([](py::module &m) {
);
);
});
});
m
.
def
(
"string_roundtrip"
,
[](
const
char
*
s
)
{
return
s
;
});
// Some test characters in utf16 and utf32 encodings. The last one (the 𝐀) contains a null byte
// Some test characters in utf16 and utf32 encodings. The last one (the 𝐀) contains a null byte
char32_t
a32
=
0x61
/*a*/
,
z32
=
0x7a
/*z*/
,
ib32
=
0x203d
/*‽*/
,
cake32
=
0x1f382
/*🎂*/
,
mathbfA32
=
0x1d400
/*𝐀*/
;
char32_t
a32
=
0x61
/*a*/
,
z32
=
0x7a
/*z*/
,
ib32
=
0x203d
/*‽*/
,
cake32
=
0x1f382
/*🎂*/
,
mathbfA32
=
0x1d400
/*𝐀*/
;
char16_t
b16
=
0x62
/*b*/
,
z16
=
0x7a
,
ib16
=
0x203d
,
cake16_1
=
0xd83c
,
cake16_2
=
0xdf82
,
mathbfA16_1
=
0xd835
,
mathbfA16_2
=
0xdc00
;
char16_t
b16
=
0x62
/*b*/
,
z16
=
0x7a
,
ib16
=
0x203d
,
cake16_1
=
0xd83c
,
cake16_2
=
0xdf82
,
mathbfA16_1
=
0xd835
,
mathbfA16_2
=
0xdc00
;
...
@@ -661,6 +675,19 @@ test_initializer python_types([](py::module &m) {
...
@@ -661,6 +675,19 @@ test_initializer python_types([](py::module &m) {
return
l
;
return
l
;
});
});
/// Issue #484: number conversion generates unhandled exceptions
m
.
def
(
"test_complex"
,
[](
float
x
)
{
return
"{}"
_s
.
format
(
x
);
});
m
.
def
(
"test_complex"
,
[](
std
::
complex
<
float
>
x
)
{
return
"({}, {})"
_s
.
format
(
x
.
real
(),
x
.
imag
());
});
/// Issue #528: templated constructor
m
.
def
(
"tpl_ctor_vector"
,
[](
std
::
vector
<
TplCtorClass
>
&
)
{});
m
.
def
(
"tpl_ctor_map"
,
[](
std
::
unordered_map
<
TplCtorClass
,
TplCtorClass
>
&
)
{});
m
.
def
(
"tpl_ctor_set"
,
[](
std
::
unordered_set
<
TplCtorClass
>
&
)
{});
#if defined(PYBIND11_HAS_OPTIONAL)
m
.
def
(
"tpl_constr_optional"
,
[](
std
::
optional
<
TplCtorClass
>
&
)
{});
#elif defined(PYBIND11_HAS_EXP_OPTIONAL)
m
.
def
(
"tpl_constr_optional"
,
[](
std
::
experimental
::
optional
<
TplCtorClass
>
&
)
{});
#endif
});
});
#if defined(_MSC_VER)
#if defined(_MSC_VER)
...
...
tests/test_python_types.py
View file @
bdfb50f3
...
@@ -452,6 +452,12 @@ def test_implicit_casting():
...
@@ -452,6 +452,12 @@ def test_implicit_casting():
assert
z
[
'l'
]
==
[
3
,
6
,
9
,
12
,
15
]
assert
z
[
'l'
]
==
[
3
,
6
,
9
,
12
,
15
]
def
test_simple_string
():
from
pybind11_tests
import
string_roundtrip
assert
string_roundtrip
(
"const char *"
)
==
"const char *"
def
test_unicode_conversion
():
def
test_unicode_conversion
():
"""Tests unicode conversion and error reporting."""
"""Tests unicode conversion and error reporting."""
import
pybind11_tests
import
pybind11_tests
...
@@ -699,3 +705,11 @@ def test_reference_wrapper():
...
@@ -699,3 +705,11 @@ def test_reference_wrapper():
assert
refwrap_iiw
(
IncrIntWrapper
(
5
))
==
5
assert
refwrap_iiw
(
IncrIntWrapper
(
5
))
==
5
assert
refwrap_call_iiw
(
IncrIntWrapper
(
10
),
refwrap_iiw
)
==
[
10
,
10
,
10
,
10
]
assert
refwrap_call_iiw
(
IncrIntWrapper
(
10
),
refwrap_iiw
)
==
[
10
,
10
,
10
,
10
]
def
test_complex_cast
():
"""#484: number conversion generates unhandled exceptions"""
from
pybind11_tests
import
test_complex
assert
test_complex
(
1
)
==
"1.0"
assert
test_complex
(
2
j
)
==
"(0.0, 2.0)"
tests/test_sequences_and_iterators.cpp
View file @
bdfb50f3
...
@@ -351,4 +351,14 @@ test_initializer sequences_and_iterators([](py::module &pm) {
...
@@ -351,4 +351,14 @@ test_initializer sequences_and_iterators([](py::module &pm) {
m
.
def
(
"tuple_iterator"
,
[](
py
::
tuple
x
)
{
return
test_random_access_iterator
(
x
);
});
m
.
def
(
"tuple_iterator"
,
[](
py
::
tuple
x
)
{
return
test_random_access_iterator
(
x
);
});
m
.
def
(
"list_iterator"
,
[](
py
::
list
x
)
{
return
test_random_access_iterator
(
x
);
});
m
.
def
(
"list_iterator"
,
[](
py
::
list
x
)
{
return
test_random_access_iterator
(
x
);
});
m
.
def
(
"sequence_iterator"
,
[](
py
::
sequence
x
)
{
return
test_random_access_iterator
(
x
);
});
m
.
def
(
"sequence_iterator"
,
[](
py
::
sequence
x
)
{
return
test_random_access_iterator
(
x
);
});
// #181: iterator passthrough did not compile
m
.
def
(
"iterator_passthrough"
,
[](
py
::
iterator
s
)
->
py
::
iterator
{
return
py
::
make_iterator
(
std
::
begin
(
s
),
std
::
end
(
s
));
});
// #388: Can't make iterators via make_iterator() with different r/v policies
static
std
::
vector
<
int
>
list
=
{
1
,
2
,
3
};
m
.
def
(
"make_iterator_1"
,
[]()
{
return
py
::
make_iterator
<
py
::
return_value_policy
::
copy
>
(
list
);
});
m
.
def
(
"make_iterator_2"
,
[]()
{
return
py
::
make_iterator
<
py
::
return_value_policy
::
automatic
>
(
list
);
});
});
});
tests/test_sequences_and_iterators.py
View file @
bdfb50f3
...
@@ -147,3 +147,20 @@ def test_python_iterator_in_cpp():
...
@@ -147,3 +147,20 @@ def test_python_iterator_in_cpp():
assert
all
(
m
.
tuple_iterator
(
tuple
(
r
)))
assert
all
(
m
.
tuple_iterator
(
tuple
(
r
)))
assert
all
(
m
.
list_iterator
(
list
(
r
)))
assert
all
(
m
.
list_iterator
(
list
(
r
)))
assert
all
(
m
.
sequence_iterator
(
r
))
assert
all
(
m
.
sequence_iterator
(
r
))
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
]
def
test_iterator_rvp
():
"""#388: Can't make iterators via make_iterator() with different r/v policies """
import
pybind11_tests.sequences_and_iterators
as
m
assert
list
(
m
.
make_iterator_1
())
==
[
1
,
2
,
3
]
assert
list
(
m
.
make_iterator_2
())
==
[
1
,
2
,
3
]
assert
not
isinstance
(
m
.
make_iterator_1
(),
type
(
m
.
make_iterator_2
()))
tests/test_smart_ptr.cpp
View file @
bdfb50f3
...
@@ -259,6 +259,18 @@ public:
...
@@ -259,6 +259,18 @@ public:
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
CustomUniquePtr
<
T
>
);
PYBIND11_DECLARE_HOLDER_TYPE
(
T
,
CustomUniquePtr
<
T
>
);
struct
ElementBase
{
virtual
void
foo
()
{
}
/* Force creation of virtual table */
};
struct
ElementA
:
ElementBase
{
ElementA
(
int
v
)
:
v
(
v
)
{
}
int
value
()
{
return
v
;
}
int
v
;
};
struct
ElementList
{
void
add
(
std
::
shared_ptr
<
ElementBase
>
e
)
{
l
.
push_back
(
e
);
}
std
::
vector
<
std
::
shared_ptr
<
ElementBase
>>
l
;
};
test_initializer
smart_ptr_and_references
([](
py
::
module
&
pm
)
{
test_initializer
smart_ptr_and_references
([](
py
::
module
&
pm
)
{
auto
m
=
pm
.
def_submodule
(
"smart_ptr"
);
auto
m
=
pm
.
def_submodule
(
"smart_ptr"
);
...
@@ -309,4 +321,21 @@ test_initializer smart_ptr_and_references([](py::module &pm) {
...
@@ -309,4 +321,21 @@ test_initializer smart_ptr_and_references([](py::module &pm) {
py
::
class_
<
HeldByDefaultHolder
>
(
m
,
"HeldByDefaultHolder"
)
py
::
class_
<
HeldByDefaultHolder
>
(
m
,
"HeldByDefaultHolder"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
init
<>
())
.
def_static
(
"load_shared_ptr"
,
[](
std
::
shared_ptr
<
HeldByDefaultHolder
>
)
{});
.
def_static
(
"load_shared_ptr"
,
[](
std
::
shared_ptr
<
HeldByDefaultHolder
>
)
{});
// #187: issue involving std::shared_ptr<> return value policy & garbage collection
py
::
class_
<
ElementBase
,
std
::
shared_ptr
<
ElementBase
>>
(
m
,
"ElementBase"
);
py
::
class_
<
ElementA
,
ElementBase
,
std
::
shared_ptr
<
ElementA
>>
(
m
,
"ElementA"
)
.
def
(
py
::
init
<
int
>
())
.
def
(
"value"
,
&
ElementA
::
value
);
py
::
class_
<
ElementList
,
std
::
shared_ptr
<
ElementList
>>
(
m
,
"ElementList"
)
.
def
(
py
::
init
<>
())
.
def
(
"add"
,
&
ElementList
::
add
)
.
def
(
"get"
,
[](
ElementList
&
el
)
{
py
::
list
list
;
for
(
auto
&
e
:
el
.
l
)
list
.
append
(
py
::
cast
(
e
));
return
list
;
});
});
});
tests/test_smart_ptr.py
View file @
bdfb50f3
...
@@ -234,3 +234,15 @@ def test_smart_ptr_from_default():
...
@@ -234,3 +234,15 @@ def test_smart_ptr_from_default():
with
pytest
.
raises
(
RuntimeError
)
as
excinfo
:
with
pytest
.
raises
(
RuntimeError
)
as
excinfo
:
HeldByDefaultHolder
.
load_shared_ptr
(
instance
)
HeldByDefaultHolder
.
load_shared_ptr
(
instance
)
assert
"Unable to load a custom holder type from a default-holder instance"
in
str
(
excinfo
)
assert
"Unable to load a custom holder type from a default-holder instance"
in
str
(
excinfo
)
def
test_shared_ptr_gc
():
"""#187: issue involving std::shared_ptr<> return value policy & garbage collection"""
from
pybind11_tests.smart_ptr
import
ElementList
,
ElementA
el
=
ElementList
()
for
i
in
range
(
10
):
el
.
add
(
ElementA
(
i
))
pytest
.
gc_collect
()
for
i
,
v
in
enumerate
(
el
.
get
()):
assert
i
==
v
.
value
()
tests/test_virtual_functions.cpp
View file @
bdfb50f3
...
@@ -311,6 +311,16 @@ void initialize_inherited_virtuals(py::module &m) {
...
@@ -311,6 +311,16 @@ void initialize_inherited_virtuals(py::module &m) {
};
};
struct
Base
{
/* for some reason MSVC2015 can't compile this if the function is pure virtual */
virtual
std
::
string
dispatch
()
const
{
return
{};
};
};
struct
DispatchIssue
:
Base
{
virtual
std
::
string
dispatch
()
const
{
PYBIND11_OVERLOAD_PURE
(
std
::
string
,
Base
,
dispatch
,
/* no arguments */
);
}
};
test_initializer
virtual_functions
([](
py
::
module
&
m
)
{
test_initializer
virtual_functions
([](
py
::
module
&
m
)
{
py
::
class_
<
ExampleVirt
,
PyExampleVirt
>
(
m
,
"ExampleVirt"
)
py
::
class_
<
ExampleVirt
,
PyExampleVirt
>
(
m
,
"ExampleVirt"
)
...
@@ -341,4 +351,51 @@ test_initializer virtual_functions([](py::module &m) {
...
@@ -341,4 +351,51 @@ test_initializer virtual_functions([](py::module &m) {
m
.
def
(
"cstats_debug"
,
&
ConstructorStats
::
get
<
ExampleVirt
>
);
m
.
def
(
"cstats_debug"
,
&
ConstructorStats
::
get
<
ExampleVirt
>
);
initialize_inherited_virtuals
(
m
);
initialize_inherited_virtuals
(
m
);
// #159: virtual function dispatch has problems with similar-named functions
py
::
class_
<
Base
,
DispatchIssue
>
(
m
,
"DispatchIssue"
)
.
def
(
py
::
init
<>
())
.
def
(
"dispatch"
,
&
Base
::
dispatch
);
m
.
def
(
"dispatch_issue_go"
,
[](
const
Base
*
b
)
{
return
b
->
dispatch
();
});
// #392/397: overridding reference-returning functions
class
OverrideTest
{
public:
struct
A
{
std
::
string
value
=
"hi"
;
};
std
::
string
v
;
A
a
;
explicit
OverrideTest
(
const
std
::
string
&
v
)
:
v
{
v
}
{}
virtual
std
::
string
str_value
()
{
return
v
;
}
virtual
std
::
string
&
str_ref
()
{
return
v
;
}
virtual
A
A_value
()
{
return
a
;
}
virtual
A
&
A_ref
()
{
return
a
;
}
};
class
PyOverrideTest
:
public
OverrideTest
{
public:
using
OverrideTest
::
OverrideTest
;
std
::
string
str_value
()
override
{
PYBIND11_OVERLOAD
(
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); }
// But we can work around it like this:
private:
std
::
string
_tmp
;
std
::
string
str_ref_helper
()
{
PYBIND11_OVERLOAD
(
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
);
}
};
py
::
class_
<
OverrideTest
::
A
>
(
m
,
"OverrideTest_A"
)
.
def_readwrite
(
"value"
,
&
OverrideTest
::
A
::
value
);
py
::
class_
<
OverrideTest
,
PyOverrideTest
>
(
m
,
"OverrideTest"
)
.
def
(
py
::
init
<
const
std
::
string
&>
())
.
def
(
"str_value"
,
&
OverrideTest
::
str_value
)
// .def("str_ref", &OverrideTest::str_ref)
.
def
(
"A_value"
,
&
OverrideTest
::
A_value
)
.
def
(
"A_ref"
,
&
OverrideTest
::
A_ref
);
});
});
tests/test_virtual_functions.py
View file @
bdfb50f3
...
@@ -257,3 +257,42 @@ def test_move_support():
...
@@ -257,3 +257,42 @@ def test_move_support():
assert
mv_stats
.
copy_constructions
==
1
assert
mv_stats
.
copy_constructions
==
1
assert
nc_stats
.
move_constructions
>=
0
assert
nc_stats
.
move_constructions
>=
0
assert
mv_stats
.
move_constructions
>=
0
assert
mv_stats
.
move_constructions
>=
0
def
test_dispatch_issue
(
msg
):
"""#159: virtual function dispatch has problems with similar-named functions"""
from
pybind11_tests
import
DispatchIssue
,
dispatch_issue_go
class
PyClass1
(
DispatchIssue
):
def
dispatch
(
self
):
return
"Yay.."
class
PyClass2
(
DispatchIssue
):
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"'
p
=
PyClass1
()
return
dispatch_issue_go
(
p
)
b
=
PyClass2
()
assert
dispatch_issue_go
(
b
)
==
"Yay.."
def
test_override_ref
():
"""#392/397: overridding reference-returning functions"""
from
pybind11_tests
import
OverrideTest
o
=
OverrideTest
(
"asdf"
)
# Not allowed (see associated .cpp comment)
# i = o.str_ref()
# assert o.str_ref() == "asdf"
assert
o
.
str_value
()
==
"asdf"
assert
o
.
A_value
()
.
value
==
"hi"
a
=
o
.
A_ref
()
assert
a
.
value
==
"hi"
a
.
value
=
"bye"
assert
a
.
value
==
"bye"
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