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)
    if (3, 8) <= env.PY < (3, 10):
        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))
Example #2
0
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_int_convert():
    class Int(object):
        def __int__(self):
            return 42

    class NotInt(object):
        pass

    class Float(object):
        def __float__(self):
            return 41.99999

    class Index(object):
        def __index__(self):
            return 42

    class IntAndIndex(object):
        def __int__(self):
            return 42

        def __index__(self):
            return 0

    class RaisingTypeErrorOnIndex(object):
        def __index__(self):
            raise TypeError

        def __int__(self):
            return 42

    class RaisingValueErrorOnIndex(object):
        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)
    if (3, 8) <= env.PY < (3, 10):
        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())