mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 14:45:12 +00:00
pytypes: Add Gotchas section about default-constructed wrapper types and py::none() (#2362)
This commit is contained in:
parent
72b06b86b3
commit
44fa79ca80
@ -15,6 +15,11 @@ Available types include :class:`handle`, :class:`object`, :class:`bool_`,
|
|||||||
:class:`iterable`, :class:`iterator`, :class:`function`, :class:`buffer`,
|
:class:`iterable`, :class:`iterator`, :class:`function`, :class:`buffer`,
|
||||||
:class:`array`, and :class:`array_t`.
|
:class:`array`, and :class:`array_t`.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
Be sure to review the :ref:`pytypes_gotchas` before using this heavily in
|
||||||
|
your C++ API.
|
||||||
|
|
||||||
Casting back and forth
|
Casting back and forth
|
||||||
======================
|
======================
|
||||||
|
|
||||||
@ -178,3 +183,25 @@ Python exceptions from wrapper classes will be thrown as a ``py::error_already_s
|
|||||||
See :ref:`Handling exceptions from Python in C++
|
See :ref:`Handling exceptions from Python in C++
|
||||||
<handling_python_exceptions_cpp>` for more information on handling exceptions
|
<handling_python_exceptions_cpp>` for more information on handling exceptions
|
||||||
raised when calling C++ wrapper classes.
|
raised when calling C++ wrapper classes.
|
||||||
|
|
||||||
|
.. _pytypes_gotchas:
|
||||||
|
|
||||||
|
Gotchas
|
||||||
|
=======
|
||||||
|
|
||||||
|
Default-Constructed Wrappers
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
When a wrapper type is default-constructed, it is **not** a valid Python object (i.e. it is not ``py::none()``). It is simply the same as
|
||||||
|
``PyObject*`` null pointer. To check for this, use
|
||||||
|
``static_cast<bool>(my_wrapper)``.
|
||||||
|
|
||||||
|
Assigning py::none() to wrappers
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
You may be tempted to use types like ``py::str`` and ``py::dict`` in C++
|
||||||
|
signatures (either pure C++, or in bound signatures), and assign them default
|
||||||
|
values of ``py::none()``. However, in a best case scenario, it will fail fast
|
||||||
|
because ``None`` is not convertible to that type (e.g. ``py::dict``), or in a
|
||||||
|
worse case scenario, it will silently work but corrupt the types you want to
|
||||||
|
work with (e.g. ``py::str(py::none())`` will yield ``"None"`` in Python).
|
||||||
|
@ -324,6 +324,16 @@ TEST_SUBMODULE(pytypes, m) {
|
|||||||
return a[py::slice(0, -1, 2)];
|
return a[py::slice(0, -1, 2)];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// See #2361
|
||||||
|
m.def("issue2361_str_implicit_copy_none", []() {
|
||||||
|
py::str is_this_none = py::none();
|
||||||
|
return is_this_none;
|
||||||
|
});
|
||||||
|
m.def("issue2361_dict_implicit_copy_none", []() {
|
||||||
|
py::dict is_this_none = py::none();
|
||||||
|
return is_this_none;
|
||||||
|
});
|
||||||
|
|
||||||
m.def("test_memoryview_object", [](py::buffer b) {
|
m.def("test_memoryview_object", [](py::buffer b) {
|
||||||
return py::memoryview(b);
|
return py::memoryview(b);
|
||||||
});
|
});
|
||||||
|
@ -326,6 +326,14 @@ def test_list_slicing():
|
|||||||
assert li[::2] == m.test_list_slicing(li)
|
assert li[::2] == m.test_list_slicing(li)
|
||||||
|
|
||||||
|
|
||||||
|
def test_issue2361():
|
||||||
|
# See issue #2361
|
||||||
|
assert m.issue2361_str_implicit_copy_none() == "None"
|
||||||
|
with pytest.raises(TypeError) as excinfo:
|
||||||
|
assert m.issue2361_dict_implicit_copy_none()
|
||||||
|
assert "'NoneType' object is not iterable" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('method, args, fmt, expected_view', [
|
@pytest.mark.parametrize('method, args, fmt, expected_view', [
|
||||||
(m.test_memoryview_object, (b'red',), 'B', b'red'),
|
(m.test_memoryview_object, (b'red',), 'B', b'red'),
|
||||||
(m.test_memoryview_buffer_info, (b'green',), 'B', b'green'),
|
(m.test_memoryview_buffer_info, (b'green',), 'B', b'green'),
|
||||||
|
Loading…
Reference in New Issue
Block a user