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
83e328f5
Commit
83e328f5
authored
Jun 09, 2017
by
Dean Moldovan
Browse files
Split test_python_types.cpp into builtin_casters, stl and pytypes
parent
bdfb50f3
Changes
22
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
296 additions
and
0 deletions
+296
-0
tests/test_stl.cpp
tests/test_stl.cpp
+163
-0
tests/test_stl.py
tests/test_stl.py
+133
-0
No files found.
tests/test_stl.cpp
0 → 100644
View file @
83e328f5
/*
tests/test_stl.cpp -- STL type casters
Copyright (c) 2017 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 <pybind11/stl.h>
// Class that can be move- and copy-constructed, but not assigned
struct
NoAssign
{
int
value
;
explicit
NoAssign
(
int
value
=
0
)
:
value
(
value
)
{
}
NoAssign
(
const
NoAssign
&
)
=
default
;
NoAssign
(
NoAssign
&&
)
=
default
;
NoAssign
&
operator
=
(
const
NoAssign
&
)
=
delete
;
NoAssign
&
operator
=
(
NoAssign
&&
)
=
delete
;
};
/// 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_SUBMODULE
(
stl
,
m
)
{
// test_vector
m
.
def
(
"cast_vector"
,
[]()
{
return
std
::
vector
<
int
>
{
1
};
});
m
.
def
(
"load_vector"
,
[](
const
std
::
vector
<
int
>
&
v
)
{
return
v
.
at
(
0
)
==
1
&&
v
.
at
(
1
)
==
2
;
});
// test_array
m
.
def
(
"cast_array"
,
[]()
{
return
std
::
array
<
int
,
2
>
{{
1
,
2
}};
});
m
.
def
(
"load_array"
,
[](
const
std
::
array
<
int
,
2
>
&
a
)
{
return
a
[
0
]
==
1
&&
a
[
1
]
==
2
;
});
// test_valarray
m
.
def
(
"cast_valarray"
,
[]()
{
return
std
::
valarray
<
int
>
{
1
,
4
,
9
};
});
m
.
def
(
"load_valarray"
,
[](
const
std
::
valarray
<
int
>&
v
)
{
return
v
.
size
()
==
3
&&
v
[
0
]
==
1
&&
v
[
1
]
==
4
&&
v
[
2
]
==
9
;
});
// test_map
m
.
def
(
"cast_map"
,
[]()
{
return
std
::
map
<
std
::
string
,
std
::
string
>
{{
"key"
,
"value"
}};
});
m
.
def
(
"load_map"
,
[](
const
std
::
map
<
std
::
string
,
std
::
string
>
&
map
)
{
return
map
.
at
(
"key"
)
==
"value"
&&
map
.
at
(
"key2"
)
==
"value2"
;
});
// test_set
m
.
def
(
"cast_set"
,
[]()
{
return
std
::
set
<
std
::
string
>
{
"key1"
,
"key2"
};
});
m
.
def
(
"load_set"
,
[](
const
std
::
set
<
std
::
string
>
&
set
)
{
return
set
.
count
(
"key1"
)
&&
set
.
count
(
"key2"
)
&&
set
.
count
(
"key3"
);
});
struct
MoveOutContainer
{
struct
Value
{
int
value
;
};
std
::
list
<
Value
>
move_list
()
const
{
return
{{
0
},
{
1
},
{
2
}};
}
};
py
::
class_
<
MoveOutContainer
::
Value
>
(
m
,
"MoveOutContainerValue"
)
.
def_readonly
(
"value"
,
&
MoveOutContainer
::
Value
::
value
);
py
::
class_
<
MoveOutContainer
>
(
m
,
"MoveOutContainer"
)
.
def
(
py
::
init
<>
())
.
def_property_readonly
(
"move_list"
,
&
MoveOutContainer
::
move_list
);
py
::
class_
<
NoAssign
>
(
m
,
"NoAssign"
,
"Class with no C++ assignment operators"
)
.
def
(
py
::
init
<>
())
.
def
(
py
::
init
<
int
>
());
#ifdef PYBIND11_HAS_OPTIONAL
m
.
attr
(
"has_optional"
)
=
true
;
using
opt_int
=
std
::
optional
<
int
>
;
using
opt_no_assign
=
std
::
optional
<
NoAssign
>
;
m
.
def
(
"double_or_zero"
,
[](
const
opt_int
&
x
)
->
int
{
return
x
.
value_or
(
0
)
*
2
;
});
m
.
def
(
"half_or_none"
,
[](
int
x
)
->
opt_int
{
return
x
?
opt_int
(
x
/
2
)
:
opt_int
();
});
m
.
def
(
"test_nullopt"
,
[](
opt_int
x
)
{
return
x
.
value_or
(
42
);
},
py
::
arg_v
(
"x"
,
std
::
nullopt
,
"None"
));
m
.
def
(
"test_no_assign"
,
[](
const
opt_no_assign
&
x
)
{
return
x
?
x
->
value
:
42
;
},
py
::
arg_v
(
"x"
,
std
::
nullopt
,
"None"
));
m
.
def
(
"nodefer_none_optional"
,
[](
std
::
optional
<
int
>
)
{
return
true
;
});
m
.
def
(
"nodefer_none_optional"
,
[](
py
::
none
)
{
return
false
;
});
#endif
#ifdef PYBIND11_HAS_EXP_OPTIONAL
m
.
attr
(
"has_exp_optional"
)
=
true
;
using
exp_opt_int
=
std
::
experimental
::
optional
<
int
>
;
using
exp_opt_no_assign
=
std
::
experimental
::
optional
<
NoAssign
>
;
m
.
def
(
"double_or_zero_exp"
,
[](
const
exp_opt_int
&
x
)
->
int
{
return
x
.
value_or
(
0
)
*
2
;
});
m
.
def
(
"half_or_none_exp"
,
[](
int
x
)
->
exp_opt_int
{
return
x
?
exp_opt_int
(
x
/
2
)
:
exp_opt_int
();
});
m
.
def
(
"test_nullopt_exp"
,
[](
exp_opt_int
x
)
{
return
x
.
value_or
(
42
);
},
py
::
arg_v
(
"x"
,
std
::
experimental
::
nullopt
,
"None"
));
m
.
def
(
"test_no_assign_exp"
,
[](
const
exp_opt_no_assign
&
x
)
{
return
x
?
x
->
value
:
42
;
},
py
::
arg_v
(
"x"
,
std
::
experimental
::
nullopt
,
"None"
));
#endif
#ifdef PYBIND11_HAS_VARIANT
struct
visitor
{
const
char
*
operator
()(
int
)
{
return
"int"
;
}
const
char
*
operator
()(
std
::
string
)
{
return
"std::string"
;
}
const
char
*
operator
()(
double
)
{
return
"double"
;
}
const
char
*
operator
()(
std
::
nullptr_t
)
{
return
"std::nullptr_t"
;
}
};
m
.
def
(
"load_variant"
,
[](
std
::
variant
<
int
,
std
::
string
,
double
,
std
::
nullptr_t
>
v
)
{
return
std
::
visit
(
visitor
(),
v
);
});
m
.
def
(
"load_variant_2pass"
,
[](
std
::
variant
<
double
,
int
>
v
)
{
return
std
::
visit
(
visitor
(),
v
);
});
m
.
def
(
"cast_variant"
,
[]()
{
using
V
=
std
::
variant
<
int
,
std
::
string
>
;
return
py
::
make_tuple
(
V
(
5
),
V
(
"Hello"
));
});
#endif
/// #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
// test_vec_of_reference_wrapper
// #171: Can't return STL structures containing reference wrapper
m
.
def
(
"return_vec_of_reference_wrapper"
,
[](
std
::
reference_wrapper
<
UserType
>
p4
)
{
static
UserType
p1
{
1
},
p2
{
2
},
p3
{
3
};
return
std
::
vector
<
std
::
reference_wrapper
<
UserType
>>
{
std
::
ref
(
p1
),
std
::
ref
(
p2
),
std
::
ref
(
p3
),
p4
};
});
}
tests/test_stl.py
0 → 100644
View file @
83e328f5
import
pytest
from
pybind11_tests
import
stl
as
m
from
pybind11_tests
import
UserType
def
test_vector
(
doc
):
"""std::vector <-> list"""
l
=
m
.
cast_vector
()
assert
l
==
[
1
]
l
.
append
(
2
)
assert
m
.
load_vector
(
l
)
assert
m
.
load_vector
(
tuple
(
l
))
assert
doc
(
m
.
cast_vector
)
==
"cast_vector() -> List[int]"
assert
doc
(
m
.
load_vector
)
==
"load_vector(arg0: List[int]) -> bool"
def
test_array
(
doc
):
"""std::array <-> list"""
l
=
m
.
cast_array
()
assert
l
==
[
1
,
2
]
assert
m
.
load_array
(
l
)
assert
doc
(
m
.
cast_array
)
==
"cast_array() -> List[int[2]]"
assert
doc
(
m
.
load_array
)
==
"load_array(arg0: List[int[2]]) -> bool"
def
test_valarray
(
doc
):
"""std::valarray <-> list"""
l
=
m
.
cast_valarray
()
assert
l
==
[
1
,
4
,
9
]
assert
m
.
load_valarray
(
l
)
assert
doc
(
m
.
cast_valarray
)
==
"cast_valarray() -> List[int]"
assert
doc
(
m
.
load_valarray
)
==
"load_valarray(arg0: List[int]) -> bool"
def
test_map
(
doc
):
"""std::map <-> dict"""
d
=
m
.
cast_map
()
assert
d
==
{
"key"
:
"value"
}
d
[
"key2"
]
=
"value2"
assert
m
.
load_map
(
d
)
assert
doc
(
m
.
cast_map
)
==
"cast_map() -> Dict[str, str]"
assert
doc
(
m
.
load_map
)
==
"load_map(arg0: Dict[str, str]) -> bool"
def
test_set
(
doc
):
"""std::set <-> set"""
s
=
m
.
cast_set
()
assert
s
==
{
"key1"
,
"key2"
}
s
.
add
(
"key3"
)
assert
m
.
load_set
(
s
)
assert
doc
(
m
.
cast_set
)
==
"cast_set() -> Set[str]"
assert
doc
(
m
.
load_set
)
==
"load_set(arg0: Set[str]) -> bool"
def
test_move_out_container
():
"""Properties use the `reference_internal` policy by default. If the underlying function
returns an rvalue, the policy is automatically changed to `move` to avoid referencing
a temporary. In case the return value is a container of user-defined types, the policy
also needs to be applied to the elements, not just the container."""
c
=
m
.
MoveOutContainer
()
moved_out_list
=
c
.
move_list
assert
[
x
.
value
for
x
in
moved_out_list
]
==
[
0
,
1
,
2
]
@
pytest
.
mark
.
skipif
(
not
hasattr
(
m
,
"has_optional"
),
reason
=
'no <optional>'
)
def
test_optional
():
assert
m
.
double_or_zero
(
None
)
==
0
assert
m
.
double_or_zero
(
42
)
==
84
pytest
.
raises
(
TypeError
,
m
.
double_or_zero
,
'foo'
)
assert
m
.
half_or_none
(
0
)
is
None
assert
m
.
half_or_none
(
42
)
==
21
pytest
.
raises
(
TypeError
,
m
.
half_or_none
,
'foo'
)
assert
m
.
test_nullopt
()
==
42
assert
m
.
test_nullopt
(
None
)
==
42
assert
m
.
test_nullopt
(
42
)
==
42
assert
m
.
test_nullopt
(
43
)
==
43
assert
m
.
test_no_assign
()
==
42
assert
m
.
test_no_assign
(
None
)
==
42
assert
m
.
test_no_assign
(
m
.
NoAssign
(
43
))
==
43
pytest
.
raises
(
TypeError
,
m
.
test_no_assign
,
43
)
assert
m
.
nodefer_none_optional
(
None
)
@
pytest
.
mark
.
skipif
(
not
hasattr
(
m
,
"has_exp_optional"
),
reason
=
'no <experimental/optional>'
)
def
test_exp_optional
():
assert
m
.
double_or_zero_exp
(
None
)
==
0
assert
m
.
double_or_zero_exp
(
42
)
==
84
pytest
.
raises
(
TypeError
,
m
.
double_or_zero_exp
,
'foo'
)
assert
m
.
half_or_none_exp
(
0
)
is
None
assert
m
.
half_or_none_exp
(
42
)
==
21
pytest
.
raises
(
TypeError
,
m
.
half_or_none_exp
,
'foo'
)
assert
m
.
test_nullopt_exp
()
==
42
assert
m
.
test_nullopt_exp
(
None
)
==
42
assert
m
.
test_nullopt_exp
(
42
)
==
42
assert
m
.
test_nullopt_exp
(
43
)
==
43
assert
m
.
test_no_assign_exp
()
==
42
assert
m
.
test_no_assign_exp
(
None
)
==
42
assert
m
.
test_no_assign_exp
(
m
.
NoAssign
(
43
))
==
43
pytest
.
raises
(
TypeError
,
m
.
test_no_assign_exp
,
43
)
@
pytest
.
mark
.
skipif
(
not
hasattr
(
m
,
"load_variant"
),
reason
=
'no <variant>'
)
def
test_variant
(
doc
):
assert
m
.
load_variant
(
1
)
==
"int"
assert
m
.
load_variant
(
"1"
)
==
"std::string"
assert
m
.
load_variant
(
1.0
)
==
"double"
assert
m
.
load_variant
(
None
)
==
"std::nullptr_t"
assert
m
.
load_variant_2pass
(
1
)
==
"int"
assert
m
.
load_variant_2pass
(
1.0
)
==
"double"
assert
m
.
cast_variant
()
==
(
5
,
"Hello"
)
assert
doc
(
m
.
load_variant
)
==
"load_variant(arg0: Union[int, str, float, None]) -> str"
def
test_vec_of_reference_wrapper
():
"""#171: Can't return reference wrappers (or STL structures containing them)"""
assert
str
(
m
.
return_vec_of_reference_wrapper
(
UserType
(
4
)))
==
\
"[UserType(1), UserType(2), UserType(3), UserType(4)]"
Prev
1
2
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