aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/pybind11/tests/test_builtin_casters.py
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/pybind11/tests/test_builtin_casters.py')
-rw-r--r--3rdparty/pybind11/tests/test_builtin_casters.py319
1 files changed, 211 insertions, 108 deletions
diff --git a/3rdparty/pybind11/tests/test_builtin_casters.py b/3rdparty/pybind11/tests/test_builtin_casters.py
index bd7996b6..d38ae680 100644
--- a/3rdparty/pybind11/tests/test_builtin_casters.py
+++ b/3rdparty/pybind11/tests/test_builtin_casters.py
@@ -1,10 +1,10 @@
-# -*- coding: utf-8 -*-
-import pytest
+import sys
-import env # noqa: F401
+import pytest
+import env
+from pybind11_tests import IncType, UserType
from pybind11_tests import builtin_casters as m
-from pybind11_tests import UserType, IncType
def test_simple_string():
@@ -13,12 +13,12 @@ def test_simple_string():
def test_unicode_conversion():
"""Tests unicode conversion and error reporting."""
- assert m.good_utf8_string() == u"Say utf8β€½ πŸŽ‚ 𝐀"
- assert m.good_utf16_string() == u"bβ€½πŸŽ‚π€z"
- assert m.good_utf32_string() == u"aπ€πŸŽ‚β€½z"
- assert m.good_wchar_string() == u"aβΈ˜π€z"
+ assert m.good_utf8_string() == "Say utf8β€½ πŸŽ‚ 𝐀"
+ assert m.good_utf16_string() == "bβ€½πŸŽ‚π€z"
+ assert m.good_utf32_string() == "aπ€πŸŽ‚β€½z"
+ assert m.good_wchar_string() == "aβΈ˜π€z"
if hasattr(m, "has_u8string"):
- assert m.good_utf8_u8string() == u"Say utf8β€½ πŸŽ‚ 𝐀"
+ assert m.good_utf8_u8string() == "Say utf8β€½ πŸŽ‚ 𝐀"
with pytest.raises(UnicodeDecodeError):
m.bad_utf8_string()
@@ -26,7 +26,7 @@ def test_unicode_conversion():
with pytest.raises(UnicodeDecodeError):
m.bad_utf16_string()
- # These are provided only if they actually fail (they don't when 32-bit and under Python 2.7)
+ # These are provided only if they actually fail (they don't when 32-bit)
if hasattr(m, "bad_utf32_string"):
with pytest.raises(UnicodeDecodeError):
m.bad_utf32_string()
@@ -38,10 +38,10 @@ def test_unicode_conversion():
m.bad_utf8_u8string()
assert m.u8_Z() == "Z"
- assert m.u8_eacute() == u"Γ©"
- assert m.u16_ibang() == u"β€½"
- assert m.u32_mathbfA() == u"𝐀"
- assert m.wchar_heart() == u"β™₯"
+ assert m.u8_eacute() == "Γ©"
+ assert m.u16_ibang() == "β€½"
+ assert m.u32_mathbfA() == "𝐀"
+ assert m.wchar_heart() == "β™₯"
if hasattr(m, "has_u8string"):
assert m.u8_char8_Z() == "Z"
@@ -50,72 +50,72 @@ def test_single_char_arguments():
"""Tests failures for passing invalid inputs to char-accepting functions"""
def toobig_message(r):
- return "Character code point not in range({0:#x})".format(r)
+ return f"Character code point not in range({r:#x})"
toolong_message = "Expected a character, but multi-character string found"
- assert m.ord_char(u"a") == 0x61 # simple ASCII
- assert m.ord_char_lv(u"b") == 0x62
+ assert m.ord_char("a") == 0x61 # simple ASCII
+ assert m.ord_char_lv("b") == 0x62
assert (
- m.ord_char(u"Γ©") == 0xE9
+ m.ord_char("Γ©") == 0xE9
) # requires 2 bytes in utf-8, but can be stuffed in a char
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char(u"Δ€") == 0x100 # requires 2 bytes, doesn't fit in a char
+ assert m.ord_char("Δ€") == 0x100 # requires 2 bytes, doesn't fit in a char
assert str(excinfo.value) == toobig_message(0x100)
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char(u"ab")
+ assert m.ord_char("ab")
assert str(excinfo.value) == toolong_message
- assert m.ord_char16(u"a") == 0x61
- assert m.ord_char16(u"Γ©") == 0xE9
- assert m.ord_char16_lv(u"Γͺ") == 0xEA
- assert m.ord_char16(u"Δ€") == 0x100
- assert m.ord_char16(u"β€½") == 0x203D
- assert m.ord_char16(u"β™₯") == 0x2665
- assert m.ord_char16_lv(u"β™‘") == 0x2661
+ assert m.ord_char16("a") == 0x61
+ assert m.ord_char16("Γ©") == 0xE9
+ assert m.ord_char16_lv("Γͺ") == 0xEA
+ assert m.ord_char16("Δ€") == 0x100
+ assert m.ord_char16("β€½") == 0x203D
+ assert m.ord_char16("β™₯") == 0x2665
+ assert m.ord_char16_lv("β™‘") == 0x2661
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char16(u"πŸŽ‚") == 0x1F382 # requires surrogate pair
+ assert m.ord_char16("πŸŽ‚") == 0x1F382 # requires surrogate pair
assert str(excinfo.value) == toobig_message(0x10000)
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char16(u"aa")
+ assert m.ord_char16("aa")
assert str(excinfo.value) == toolong_message
- assert m.ord_char32(u"a") == 0x61
- assert m.ord_char32(u"Γ©") == 0xE9
- assert m.ord_char32(u"Δ€") == 0x100
- assert m.ord_char32(u"β€½") == 0x203D
- assert m.ord_char32(u"β™₯") == 0x2665
- assert m.ord_char32(u"πŸŽ‚") == 0x1F382
+ assert m.ord_char32("a") == 0x61
+ assert m.ord_char32("Γ©") == 0xE9
+ assert m.ord_char32("Δ€") == 0x100
+ assert m.ord_char32("β€½") == 0x203D
+ assert m.ord_char32("β™₯") == 0x2665
+ assert m.ord_char32("πŸŽ‚") == 0x1F382
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char32(u"aa")
+ assert m.ord_char32("aa")
assert str(excinfo.value) == toolong_message
- assert m.ord_wchar(u"a") == 0x61
- assert m.ord_wchar(u"Γ©") == 0xE9
- assert m.ord_wchar(u"Δ€") == 0x100
- assert m.ord_wchar(u"β€½") == 0x203D
- assert m.ord_wchar(u"β™₯") == 0x2665
+ assert m.ord_wchar("a") == 0x61
+ assert m.ord_wchar("Γ©") == 0xE9
+ assert m.ord_wchar("Δ€") == 0x100
+ assert m.ord_wchar("β€½") == 0x203D
+ assert m.ord_wchar("β™₯") == 0x2665
if m.wchar_size == 2:
with pytest.raises(ValueError) as excinfo:
- assert m.ord_wchar(u"πŸŽ‚") == 0x1F382 # requires surrogate pair
+ assert m.ord_wchar("πŸŽ‚") == 0x1F382 # requires surrogate pair
assert str(excinfo.value) == toobig_message(0x10000)
else:
- assert m.ord_wchar(u"πŸŽ‚") == 0x1F382
+ assert m.ord_wchar("πŸŽ‚") == 0x1F382
with pytest.raises(ValueError) as excinfo:
- assert m.ord_wchar(u"aa")
+ assert m.ord_wchar("aa")
assert str(excinfo.value) == toolong_message
if hasattr(m, "has_u8string"):
- assert m.ord_char8(u"a") == 0x61 # simple ASCII
- assert m.ord_char8_lv(u"b") == 0x62
+ assert m.ord_char8("a") == 0x61 # simple ASCII
+ assert m.ord_char8_lv("b") == 0x62
assert (
- m.ord_char8(u"Γ©") == 0xE9
+ m.ord_char8("Γ©") == 0xE9
) # requires 2 bytes in utf-8, but can be stuffed in a char
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char8(u"Δ€") == 0x100 # requires 2 bytes, doesn't fit in a char
+ assert m.ord_char8("Δ€") == 0x100 # requires 2 bytes, doesn't fit in a char
assert str(excinfo.value) == toobig_message(0x100)
with pytest.raises(ValueError) as excinfo:
- assert m.ord_char8(u"ab")
+ assert m.ord_char8("ab")
assert str(excinfo.value) == toolong_message
@@ -124,18 +124,22 @@ def test_bytes_to_string():
one-way: the only way to return bytes to Python is via the pybind11::bytes class."""
# Issue #816
- def to_bytes(s):
- b = s if env.PY2 else s.encode("utf8")
- assert isinstance(b, bytes)
- return b
-
- assert m.strlen(to_bytes("hi")) == 2
- assert m.string_length(to_bytes("world")) == 5
- assert m.string_length(to_bytes("a\x00b")) == 3
- assert m.strlen(to_bytes("a\x00b")) == 1 # C-string limitation
+ assert m.strlen(b"hi") == 2
+ assert m.string_length(b"world") == 5
+ assert m.string_length("a\x00b".encode()) == 3
+ assert m.strlen("a\x00b".encode()) == 1 # C-string limitation
# passing in a utf8 encoded string should work
- assert m.string_length(u"πŸ’©".encode("utf8")) == 4
+ assert m.string_length("πŸ’©".encode()) == 4
+
+
+def test_bytearray_to_string():
+ """Tests the ability to pass bytearray to C++ string-accepting functions"""
+ assert m.string_length(bytearray(b"Hi")) == 2
+ assert m.strlen(bytearray(b"bytearray")) == 9
+ assert m.string_length(bytearray()) == 0
+ assert m.string_length(bytearray("🦜", "utf-8", "strict")) == 4
+ assert m.string_length(bytearray(b"\x80")) == 1
@pytest.mark.skipif(not hasattr(m, "has_string_view"), reason="no <string_view>")
@@ -143,26 +147,26 @@ def test_string_view(capture):
"""Tests support for C++17 string_view arguments and return values"""
assert m.string_view_chars("Hi") == [72, 105]
assert m.string_view_chars("Hi πŸŽ‚") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
- assert m.string_view16_chars(u"Hi πŸŽ‚") == [72, 105, 32, 0xD83C, 0xDF82]
- assert m.string_view32_chars(u"Hi πŸŽ‚") == [72, 105, 32, 127874]
+ assert m.string_view16_chars("Hi πŸŽ‚") == [72, 105, 32, 0xD83C, 0xDF82]
+ assert m.string_view32_chars("Hi πŸŽ‚") == [72, 105, 32, 127874]
if hasattr(m, "has_u8string"):
assert m.string_view8_chars("Hi") == [72, 105]
- assert m.string_view8_chars(u"Hi πŸŽ‚") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
+ assert m.string_view8_chars("Hi πŸŽ‚") == [72, 105, 32, 0xF0, 0x9F, 0x8E, 0x82]
- assert m.string_view_return() == u"utf8 secret πŸŽ‚"
- assert m.string_view16_return() == u"utf16 secret πŸŽ‚"
- assert m.string_view32_return() == u"utf32 secret πŸŽ‚"
+ assert m.string_view_return() == "utf8 secret πŸŽ‚"
+ assert m.string_view16_return() == "utf16 secret πŸŽ‚"
+ assert m.string_view32_return() == "utf32 secret πŸŽ‚"
if hasattr(m, "has_u8string"):
- assert m.string_view8_return() == u"utf8 secret πŸŽ‚"
+ assert m.string_view8_return() == "utf8 secret πŸŽ‚"
with capture:
m.string_view_print("Hi")
m.string_view_print("utf8 πŸŽ‚")
- m.string_view16_print(u"utf16 πŸŽ‚")
- m.string_view32_print(u"utf32 πŸŽ‚")
+ m.string_view16_print("utf16 πŸŽ‚")
+ m.string_view32_print("utf32 πŸŽ‚")
assert (
capture
- == u"""
+ == """
Hi 2
utf8 πŸŽ‚ 9
utf16 πŸŽ‚ 8
@@ -172,10 +176,10 @@ def test_string_view(capture):
if hasattr(m, "has_u8string"):
with capture:
m.string_view8_print("Hi")
- m.string_view8_print(u"utf8 πŸŽ‚")
+ m.string_view8_print("utf8 πŸŽ‚")
assert (
capture
- == u"""
+ == """
Hi 2
utf8 πŸŽ‚ 9
"""
@@ -184,11 +188,11 @@ def test_string_view(capture):
with capture:
m.string_view_print("Hi, ascii")
m.string_view_print("Hi, utf8 πŸŽ‚")
- m.string_view16_print(u"Hi, utf16 πŸŽ‚")
- m.string_view32_print(u"Hi, utf32 πŸŽ‚")
+ m.string_view16_print("Hi, utf16 πŸŽ‚")
+ m.string_view32_print("Hi, utf32 πŸŽ‚")
assert (
capture
- == u"""
+ == """
Hi, ascii 9
Hi, utf8 πŸŽ‚ 13
Hi, utf16 πŸŽ‚ 12
@@ -198,15 +202,25 @@ def test_string_view(capture):
if hasattr(m, "has_u8string"):
with capture:
m.string_view8_print("Hi, ascii")
- m.string_view8_print(u"Hi, utf8 πŸŽ‚")
+ m.string_view8_print("Hi, utf8 πŸŽ‚")
assert (
capture
- == u"""
+ == """
Hi, ascii 9
Hi, utf8 πŸŽ‚ 13
"""
)
+ assert m.string_view_bytes() == b"abc \x80\x80 def"
+ assert m.string_view_str() == "abc β€½ def"
+ assert m.string_view_from_bytes("abc β€½ def".encode()) == "abc β€½ def"
+ if hasattr(m, "has_u8string"):
+ assert m.string_view8_str() == "abc β€½ def"
+ 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():
"""Issue #929 - out-of-range integer values shouldn't be accepted"""
@@ -214,20 +228,8 @@ def test_integer_casting():
assert m.i64_str(-1) == "-1"
assert m.i32_str(2000000000) == "2000000000"
assert m.u32_str(2000000000) == "2000000000"
- if env.PY2:
- assert m.i32_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
- assert m.i64_str(long(-1)) == "-1" # noqa: F821 undefined name 'long'
- assert (
- m.i64_str(long(-999999999999)) # noqa: F821 undefined name 'long'
- == "-999999999999"
- )
- assert (
- m.u64_str(long(999999999999)) # noqa: F821 undefined name 'long'
- == "999999999999"
- )
- else:
- assert m.i64_str(-999999999999) == "-999999999999"
- assert m.u64_str(999999999999) == "999999999999"
+ assert m.i64_str(-999999999999) == "-999999999999"
+ assert m.u64_str(999999999999) == "999999999999"
with pytest.raises(TypeError) as excinfo:
m.u32_str(-1)
@@ -242,13 +244,100 @@ def test_integer_casting():
m.i32_str(3000000000)
assert "incompatible function arguments" in str(excinfo.value)
- if env.PY2:
- with pytest.raises(TypeError) as excinfo:
- m.u32_str(long(-1)) # noqa: F821 undefined name 'long'
- assert "incompatible function arguments" in str(excinfo.value)
- with pytest.raises(TypeError) as excinfo:
- m.u64_str(long(-1)) # noqa: F821 undefined name 'long'
- assert "incompatible function arguments" in str(excinfo.value)
+
+def test_int_convert():
+ class Int:
+ def __int__(self):
+ return 42
+
+ class NotInt:
+ pass
+
+ class Float:
+ def __float__(self):
+ return 41.99999
+
+ class Index:
+ def __index__(self):
+ return 42
+
+ class IntAndIndex:
+ def __int__(self):
+ return 42
+
+ def __index__(self):
+ return 0
+
+ class RaisingTypeErrorOnIndex:
+ def __index__(self):
+ raise TypeError
+
+ def __int__(self):
+ return 42
+
+ class RaisingValueErrorOnIndex:
+ def __index__(self):
+ raise ValueError
+
+ def __int__(self):
+ return 42
+
+ convert, noconvert = m.int_passthrough, m.int_passthrough_noconvert
+
+ def requires_conversion(v):
+ pytest.raises(TypeError, noconvert, v)
+
+ def cant_convert(v):
+ pytest.raises(TypeError, convert, v)
+
+ assert convert(7) == 7
+ assert noconvert(7) == 7
+ cant_convert(3.14159)
+ # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
+ # TODO: PyPy 3.8 does not behave like CPython 3.8 here yet (7.3.7)
+ if (3, 8) <= sys.version_info < (3, 10) and env.CPYTHON:
+ with env.deprecated_call():
+ assert convert(Int()) == 42
+ else:
+ assert convert(Int()) == 42
+ requires_conversion(Int())
+ cant_convert(NotInt())
+ cant_convert(Float())
+
+ # Before Python 3.8, `PyLong_AsLong` does not pick up on `obj.__index__`,
+ # but pybind11 "backports" this behavior.
+ assert convert(Index()) == 42
+ assert noconvert(Index()) == 42
+ assert convert(IntAndIndex()) == 0 # Fishy; `int(DoubleThought)` == 42
+ assert noconvert(IntAndIndex()) == 0
+ assert convert(RaisingTypeErrorOnIndex()) == 42
+ requires_conversion(RaisingTypeErrorOnIndex())
+ assert convert(RaisingValueErrorOnIndex()) == 42
+ requires_conversion(RaisingValueErrorOnIndex())
+
+
+def test_numpy_int_convert():
+ np = pytest.importorskip("numpy")
+
+ convert, noconvert = m.int_passthrough, m.int_passthrough_noconvert
+
+ def require_implicit(v):
+ pytest.raises(TypeError, noconvert, v)
+
+ # `np.intc` is an alias that corresponds to a C++ `int`
+ assert convert(np.intc(42)) == 42
+ assert noconvert(np.intc(42)) == 42
+
+ # The implicit conversion from np.float32 is undesirable but currently accepted.
+ # TODO: Avoid DeprecationWarning in `PyLong_AsLong` (and similar)
+ # 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) <= sys.version_info < (3, 10) and env.CPYTHON:
+ with env.deprecated_call():
+ assert convert(np.float32(3.14159)) == 3
+ else:
+ assert convert(np.float32(3.14159)) == 3
+ require_implicit(np.float32(3.14159))
def test_tuple(doc):
@@ -315,6 +404,7 @@ def test_reference_wrapper():
"""std::reference_wrapper for builtin and user types"""
assert m.refwrap_builtin(42) == 420
assert m.refwrap_usertype(UserType(42)) == 42
+ assert m.refwrap_usertype_const(UserType(42)) == 42
with pytest.raises(TypeError) as excinfo:
m.refwrap_builtin(None)
@@ -324,6 +414,9 @@ def test_reference_wrapper():
m.refwrap_usertype(None)
assert "incompatible function arguments" in str(excinfo.value)
+ assert m.refwrap_lvalue().value == 1
+ assert m.refwrap_lvalue_const().value == 1
+
a1 = m.refwrap_list(copy=True)
a2 = m.refwrap_list(copy=True)
assert [x.value for x in a1] == [2, 3]
@@ -366,7 +459,7 @@ def test_bool_caster():
require_implicit(None)
assert convert(None) is False
- class A(object):
+ class A:
def __init__(self, x):
self.x = x
@@ -376,7 +469,7 @@ def test_bool_caster():
def __bool__(self):
return self.x
- class B(object):
+ class B:
pass
# Arbitrary objects are not accepted
@@ -406,18 +499,28 @@ def test_numpy_bool():
def test_int_long():
- """In Python 2, a C++ int should return a Python int rather than long
- if possible: longs are not always accepted where ints are used (such
- as the argument to sys.exit()). A C++ long long is always a Python
- long."""
-
- import sys
-
- must_be_long = type(getattr(sys, "maxint", 1) + 1)
assert isinstance(m.int_cast(), int)
assert isinstance(m.long_cast(), int)
- assert isinstance(m.longlong_cast(), must_be_long)
+ assert isinstance(m.longlong_cast(), int)
def test_void_caster_2():
assert m.test_void_caster()
+
+
+def test_const_ref_caster():
+ """Verifies that const-ref is propagated through type_caster cast_op.
+ The returned ConstRefCasted type is a minimal type that is constructed to
+ reference the casting mode used.
+ """
+ x = False
+ assert m.takes(x) == 1
+ assert m.takes_move(x) == 1
+
+ assert m.takes_ptr(x) == 3
+ assert m.takes_ref(x) == 2
+ assert m.takes_ref_wrap(x) == 2
+
+ assert m.takes_const_ptr(x) == 5
+ assert m.takes_const_ref(x) == 4
+ assert m.takes_const_ref_wrap(x) == 4