Unverified Commit e315e1fe authored by Henry Schreiner's avatar Henry Schreiner
Browse files

Merge branch 'master' into stable

parents 71fd5241 97976c16
...@@ -4,7 +4,6 @@ import os ...@@ -4,7 +4,6 @@ import os
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import eval_ as m from pybind11_tests import eval_ as m
...@@ -33,3 +32,20 @@ def test_eval_empty_globals(): ...@@ -33,3 +32,20 @@ def test_eval_empty_globals():
g = {} g = {}
assert "__builtins__" in m.eval_empty_globals(g) assert "__builtins__" in m.eval_empty_globals(g)
assert "__builtins__" in g assert "__builtins__" in g
def test_eval_closure():
global_, local = m.test_eval_closure()
assert global_["closure_value"] == 42
assert local["closure_value"] == 0
assert "local_value" not in global_
assert local["local_value"] == 0
assert "func_global" not in global_
assert local["func_global"]() == 42
assert "func_local" not in global_
with pytest.raises(NameError):
local["func_local"]()
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
All rights reserved. Use of this source code is governed by a All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file. BSD-style license that can be found in the LICENSE file.
*/ */
#include "test_exceptions.h" #include "test_exceptions.h"
#include "local_bindings.h"
#include "pybind11_tests.h" #include "pybind11_tests.h"
#include <utility> #include <utility>
...@@ -68,8 +69,19 @@ class MyException5_1 : public MyException5 { ...@@ -68,8 +69,19 @@ class MyException5_1 : public MyException5 {
using MyException5::MyException5; using MyException5::MyException5;
}; };
// Exception that will be caught via the module local translator.
class MyException6 : public std::exception {
public:
explicit MyException6(const char * m) : message{m} {}
const char * what() const noexcept override {return message.c_str();}
private:
std::string message = "";
};
struct PythonCallInDestructor { struct PythonCallInDestructor {
PythonCallInDestructor(const py::dict &d) : d(d) {} explicit PythonCallInDestructor(const py::dict &d) : d(d) {}
~PythonCallInDestructor() { d["good"] = true; } ~PythonCallInDestructor() { d["good"] = true; }
py::dict d; py::dict d;
...@@ -78,7 +90,7 @@ struct PythonCallInDestructor { ...@@ -78,7 +90,7 @@ struct PythonCallInDestructor {
struct PythonAlreadySetInDestructor { struct PythonAlreadySetInDestructor {
PythonAlreadySetInDestructor(const py::str &s) : s(s) {} explicit PythonAlreadySetInDestructor(const py::str &s) : s(s) {}
~PythonAlreadySetInDestructor() { ~PythonAlreadySetInDestructor() {
py::dict foo; py::dict foo;
try { try {
...@@ -138,14 +150,29 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -138,14 +150,29 @@ TEST_SUBMODULE(exceptions, m) {
// A slightly more complicated one that declares MyException5_1 as a subclass of MyException5 // A slightly more complicated one that declares MyException5_1 as a subclass of MyException5
py::register_exception<MyException5_1>(m, "MyException5_1", ex5.ptr()); py::register_exception<MyException5_1>(m, "MyException5_1", ex5.ptr());
//py::register_local_exception<LocalSimpleException>(m, "LocalSimpleException")
py::register_local_exception_translator([](std::exception_ptr p) {
try {
if (p) {
std::rethrow_exception(p);
}
} catch (const MyException6 &e) {
PyErr_SetString(PyExc_RuntimeError, e.what());
}
});
m.def("throws1", []() { throw MyException("this error should go to a custom type"); }); m.def("throws1", []() { throw MyException("this error should go to a custom type"); });
m.def("throws2", []() { throw MyException2("this error should go to a standard Python exception"); }); m.def("throws2", []() { throw MyException2("this error should go to a standard Python exception"); });
m.def("throws3", []() { throw MyException3("this error cannot be translated"); }); m.def("throws3", []() { throw MyException3("this error cannot be translated"); });
m.def("throws4", []() { throw MyException4("this error is rethrown"); }); m.def("throws4", []() { throw MyException4("this error is rethrown"); });
m.def("throws5", []() { throw MyException5("this is a helper-defined translated exception"); }); m.def("throws5", []() { throw MyException5("this is a helper-defined translated exception"); });
m.def("throws5_1", []() { throw MyException5_1("MyException5 subclass"); }); m.def("throws5_1", []() { throw MyException5_1("MyException5 subclass"); });
m.def("throws6", []() { throw MyException6("MyException6 only handled in this module"); });
m.def("throws_logic_error", []() { throw std::logic_error("this error should fall through to the standard handler"); }); m.def("throws_logic_error", []() { throw std::logic_error("this error should fall through to the standard handler"); });
m.def("throws_overflow_error", []() {throw std::overflow_error(""); }); m.def("throws_overflow_error", []() { throw std::overflow_error(""); });
m.def("throws_local_error", []() { throw LocalException("never caught"); });
m.def("throws_local_simple_error", []() { throw LocalSimpleException("this mod"); });
m.def("exception_matches", []() { m.def("exception_matches", []() {
py::dict foo; py::dict foo;
try { try {
...@@ -235,4 +262,24 @@ TEST_SUBMODULE(exceptions, m) { ...@@ -235,4 +262,24 @@ TEST_SUBMODULE(exceptions, m) {
m.def("simple_bool_passthrough", [](bool x) {return x;}); m.def("simple_bool_passthrough", [](bool x) {return x;});
m.def("throw_should_be_translated_to_key_error", []() { throw shared_exception(); }); m.def("throw_should_be_translated_to_key_error", []() { throw shared_exception(); });
#if PY_VERSION_HEX >= 0x03030000
m.def("raise_from", []() {
PyErr_SetString(PyExc_ValueError, "inner");
py::raise_from(PyExc_ValueError, "outer");
throw py::error_already_set();
});
m.def("raise_from_already_set", []() {
try {
PyErr_SetString(PyExc_ValueError, "inner");
throw py::error_already_set();
} catch (py::error_already_set& e) {
py::raise_from(e, PyExc_ValueError, "outer");
throw py::error_already_set();
}
});
#endif
} }
...@@ -4,9 +4,8 @@ import sys ...@@ -4,9 +4,8 @@ import sys
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import exceptions as m
import pybind11_cross_module_tests as cm import pybind11_cross_module_tests as cm
from pybind11_tests import exceptions as m
def test_std_exception(msg): def test_std_exception(msg):
...@@ -25,7 +24,23 @@ def test_error_already_set(msg): ...@@ -25,7 +24,23 @@ def test_error_already_set(msg):
assert msg(excinfo.value) == "foo" assert msg(excinfo.value) == "foo"
def test_cross_module_exceptions(): @pytest.mark.skipif("env.PY2")
def test_raise_from(msg):
with pytest.raises(ValueError) as excinfo:
m.raise_from()
assert msg(excinfo.value) == "outer"
assert msg(excinfo.value.__cause__) == "inner"
@pytest.mark.skipif("env.PY2")
def test_raise_from_already_set(msg):
with pytest.raises(ValueError) as excinfo:
m.raise_from_already_set()
assert msg(excinfo.value) == "outer"
assert msg(excinfo.value.__cause__) == "inner"
def test_cross_module_exceptions(msg):
with pytest.raises(RuntimeError) as excinfo: with pytest.raises(RuntimeError) as excinfo:
cm.raise_runtime_error() cm.raise_runtime_error()
assert str(excinfo.value) == "My runtime error" assert str(excinfo.value) == "My runtime error"
...@@ -45,6 +60,15 @@ def test_cross_module_exceptions(): ...@@ -45,6 +60,15 @@ def test_cross_module_exceptions():
with pytest.raises(StopIteration) as excinfo: with pytest.raises(StopIteration) as excinfo:
cm.throw_stop_iteration() cm.throw_stop_iteration()
with pytest.raises(cm.LocalSimpleException) as excinfo:
cm.throw_local_simple_error()
assert msg(excinfo.value) == "external mod"
with pytest.raises(KeyError) as excinfo:
cm.throw_local_error()
# KeyError is a repr of the key, so it has an extra set of quotes
assert str(excinfo.value) == "'just local'"
# TODO: FIXME # TODO: FIXME
@pytest.mark.xfail( @pytest.mark.xfail(
...@@ -221,3 +245,21 @@ def test_invalid_repr(): ...@@ -221,3 +245,21 @@ def test_invalid_repr():
with pytest.raises(TypeError): with pytest.raises(TypeError):
m.simple_bool_passthrough(MyRepr()) m.simple_bool_passthrough(MyRepr())
def test_local_translator(msg):
"""Tests that a local translator works and that the local translator from
the cross module is not applied"""
with pytest.raises(RuntimeError) as excinfo:
m.throws6()
assert msg(excinfo.value) == "MyException6 only handled in this module"
with pytest.raises(RuntimeError) as excinfo:
m.throws_local_error()
assert not isinstance(excinfo.value, KeyError)
assert msg(excinfo.value) == "never caught"
with pytest.raises(Exception) as excinfo:
m.throws_local_simple_error()
assert not isinstance(excinfo.value, cm.LocalSimpleException)
assert msg(excinfo.value) == "this mod"
...@@ -19,8 +19,9 @@ ...@@ -19,8 +19,9 @@
class TestFactory1 { class TestFactory1 {
friend class TestFactoryHelper; friend class TestFactoryHelper;
TestFactory1() : value("(empty)") { print_default_created(this); } TestFactory1() : value("(empty)") { print_default_created(this); }
TestFactory1(int v) : value(std::to_string(v)) { print_created(this, value); } explicit TestFactory1(int v) : value(std::to_string(v)) { print_created(this, value); }
TestFactory1(std::string v) : value(std::move(v)) { print_created(this, value); } explicit TestFactory1(std::string v) : value(std::move(v)) { print_created(this, value); }
public: public:
std::string value; std::string value;
TestFactory1(TestFactory1 &&) = delete; TestFactory1(TestFactory1 &&) = delete;
...@@ -33,8 +34,9 @@ public: ...@@ -33,8 +34,9 @@ public:
class TestFactory2 { class TestFactory2 {
friend class TestFactoryHelper; friend class TestFactoryHelper;
TestFactory2() : value("(empty2)") { print_default_created(this); } TestFactory2() : value("(empty2)") { print_default_created(this); }
TestFactory2(int v) : value(std::to_string(v)) { print_created(this, value); } explicit TestFactory2(int v) : value(std::to_string(v)) { print_created(this, value); }
TestFactory2(std::string v) : value(std::move(v)) { print_created(this, value); } explicit TestFactory2(std::string v) : value(std::move(v)) { print_created(this, value); }
public: public:
TestFactory2(TestFactory2 &&m) noexcept { TestFactory2(TestFactory2 &&m) noexcept {
value = std::move(m.value); value = std::move(m.value);
...@@ -53,9 +55,10 @@ class TestFactory3 { ...@@ -53,9 +55,10 @@ class TestFactory3 {
protected: protected:
friend class TestFactoryHelper; friend class TestFactoryHelper;
TestFactory3() : value("(empty3)") { print_default_created(this); } TestFactory3() : value("(empty3)") { print_default_created(this); }
TestFactory3(int v) : value(std::to_string(v)) { print_created(this, value); } explicit TestFactory3(int v) : value(std::to_string(v)) { print_created(this, value); }
public: public:
TestFactory3(std::string v) : value(std::move(v)) { print_created(this, value); } explicit TestFactory3(std::string v) : value(std::move(v)) { print_created(this, value); }
TestFactory3(TestFactory3 &&m) noexcept { TestFactory3(TestFactory3 &&m) noexcept {
value = std::move(m.value); value = std::move(m.value);
print_move_created(this); print_move_created(this);
...@@ -72,13 +75,13 @@ public: ...@@ -72,13 +75,13 @@ public:
class TestFactory4 : public TestFactory3 { class TestFactory4 : public TestFactory3 {
public: public:
TestFactory4() : TestFactory3() { print_default_created(this); } TestFactory4() : TestFactory3() { print_default_created(this); }
TestFactory4(int v) : TestFactory3(v) { print_created(this, v); } explicit TestFactory4(int v) : TestFactory3(v) { print_created(this, v); }
~TestFactory4() override { print_destroyed(this); } ~TestFactory4() override { print_destroyed(this); }
}; };
// Another class for an invalid downcast test // Another class for an invalid downcast test
class TestFactory5 : public TestFactory3 { class TestFactory5 : public TestFactory3 {
public: public:
TestFactory5(int i) : TestFactory3(i) { print_created(this, i); } explicit TestFactory5(int i) : TestFactory3(i) { print_created(this, i); }
~TestFactory5() override { print_destroyed(this); } ~TestFactory5() override { print_destroyed(this); }
}; };
...@@ -87,7 +90,7 @@ protected: ...@@ -87,7 +90,7 @@ protected:
int value; int value;
bool alias = false; bool alias = false;
public: public:
TestFactory6(int i) : value{i} { print_created(this, i); } explicit TestFactory6(int i) : value{i} { print_created(this, i); }
TestFactory6(TestFactory6 &&f) noexcept { TestFactory6(TestFactory6 &&f) noexcept {
print_move_created(this); print_move_created(this);
value = f.value; value = f.value;
...@@ -102,11 +105,20 @@ class PyTF6 : public TestFactory6 { ...@@ -102,11 +105,20 @@ class PyTF6 : public TestFactory6 {
public: public:
// Special constructor that allows the factory to construct a PyTF6 from a TestFactory6 only // Special constructor that allows the factory to construct a PyTF6 from a TestFactory6 only
// when an alias is needed: // when an alias is needed:
PyTF6(TestFactory6 &&base) : TestFactory6(std::move(base)) { alias = true; print_created(this, "move", value); } explicit PyTF6(TestFactory6 &&base) : TestFactory6(std::move(base)) {
PyTF6(int i) : TestFactory6(i) { alias = true; print_created(this, i); } alias = true;
print_created(this, "move", value);
}
explicit PyTF6(int i) : TestFactory6(i) {
alias = true;
print_created(this, i);
}
PyTF6(PyTF6 &&f) noexcept : TestFactory6(std::move(f)) { print_move_created(this); } PyTF6(PyTF6 &&f) noexcept : TestFactory6(std::move(f)) { print_move_created(this); }
PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); } PyTF6(const PyTF6 &f) : TestFactory6(f) { print_copy_created(this); }
PyTF6(std::string s) : TestFactory6((int) s.size()) { alias = true; print_created(this, s); } explicit PyTF6(std::string s) : TestFactory6((int) s.size()) {
alias = true;
print_created(this, s);
}
~PyTF6() override { print_destroyed(this); } ~PyTF6() override { print_destroyed(this); }
int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); } int get() override { PYBIND11_OVERRIDE(int, TestFactory6, get, /*no args*/); }
}; };
...@@ -116,7 +128,7 @@ protected: ...@@ -116,7 +128,7 @@ protected:
int value; int value;
bool alias = false; bool alias = false;
public: public:
TestFactory7(int i) : value{i} { print_created(this, i); } explicit TestFactory7(int i) : value{i} { print_created(this, i); }
TestFactory7(TestFactory7 &&f) noexcept { TestFactory7(TestFactory7 &&f) noexcept {
print_move_created(this); print_move_created(this);
value = f.value; value = f.value;
...@@ -129,7 +141,10 @@ public: ...@@ -129,7 +141,10 @@ public:
}; };
class PyTF7 : public TestFactory7 { class PyTF7 : public TestFactory7 {
public: public:
PyTF7(int i) : TestFactory7(i) { alias = true; print_created(this, i); } explicit PyTF7(int i) : TestFactory7(i) {
alias = true;
print_created(this, i);
}
PyTF7(PyTF7 &&f) noexcept : TestFactory7(std::move(f)) { print_move_created(this); } PyTF7(PyTF7 &&f) noexcept : TestFactory7(std::move(f)) { print_move_created(this); }
PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); } PyTF7(const PyTF7 &f) : TestFactory7(f) { print_copy_created(this); }
~PyTF7() override { print_destroyed(this); } ~PyTF7() override { print_destroyed(this); }
...@@ -300,7 +315,7 @@ TEST_SUBMODULE(factory_constructors, m) { ...@@ -300,7 +315,7 @@ TEST_SUBMODULE(factory_constructors, m) {
// Class with a custom new operator but *without* a placement new operator (issue #948) // Class with a custom new operator but *without* a placement new operator (issue #948)
class NoPlacementNew { class NoPlacementNew {
public: public:
NoPlacementNew(int i) : i(i) { } explicit NoPlacementNew(int i) : i(i) {}
static void *operator new(std::size_t s) { static void *operator new(std::size_t s) {
auto *p = ::operator new(s); auto *p = ::operator new(s);
py::print("operator new called, returning", reinterpret_cast<uintptr_t>(p)); py::print("operator new called, returning", reinterpret_cast<uintptr_t>(p));
...@@ -324,8 +339,8 @@ TEST_SUBMODULE(factory_constructors, m) { ...@@ -324,8 +339,8 @@ TEST_SUBMODULE(factory_constructors, m) {
// Class that has verbose operator_new/operator_delete calls // Class that has verbose operator_new/operator_delete calls
struct NoisyAlloc { struct NoisyAlloc {
NoisyAlloc(const NoisyAlloc &) = default; NoisyAlloc(const NoisyAlloc &) = default;
NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); } explicit NoisyAlloc(int i) { py::print(py::str("NoisyAlloc(int {})").format(i)); }
NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); } explicit NoisyAlloc(double d) { py::print(py::str("NoisyAlloc(double {})").format(d)); }
~NoisyAlloc() { py::print("~NoisyAlloc()"); } ~NoisyAlloc() { py::print("~NoisyAlloc()"); }
static void *operator new(size_t s) { py::print("noisy new"); return ::operator new(s); } static void *operator new(size_t s) { py::print("noisy new"); return ::operator new(s); }
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import pytest
import re import re
import env # noqa: F401 import pytest
import env # noqa: F401
from pybind11_tests import ConstructorStats
from pybind11_tests import factory_constructors as m from pybind11_tests import factory_constructors as m
from pybind11_tests.factory_constructors import tag from pybind11_tests.factory_constructors import tag
from pybind11_tests import ConstructorStats
def test_init_factory_basic(): def test_init_factory_basic():
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from pybind11_tests import iostream as m
import sys import sys
from contextlib import contextmanager from contextlib import contextmanager
from pybind11_tests import iostream as m
try: try:
# Python 3 # Python 3
from io import StringIO from io import StringIO
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import kwargs_and_defaults as m from pybind11_tests import kwargs_and_defaults as m
......
...@@ -78,7 +78,7 @@ TEST_SUBMODULE(local_bindings, m) { ...@@ -78,7 +78,7 @@ TEST_SUBMODULE(local_bindings, m) {
m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); }); m.def("get_mixed_lg", [](int i) { return MixedLocalGlobal(i); });
// test_internal_locals_differ // test_internal_locals_differ
m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::registered_local_types_cpp(); }); m.def("local_cpp_types_addr", []() { return (uintptr_t) &py::detail::get_local_internals().registered_types_cpp; });
// test_stl_caster_vs_stl_bind // test_stl_caster_vs_stl_bind
m.def("load_vector_via_caster", [](std::vector<int> v) { m.def("load_vector_via_caster", [](std::vector<int> v) {
...@@ -91,7 +91,7 @@ TEST_SUBMODULE(local_bindings, m) { ...@@ -91,7 +91,7 @@ TEST_SUBMODULE(local_bindings, m) {
class Cat : public pets::Pet { class Cat : public pets::Pet {
public: public:
Cat(std::string name) : Pet(std::move(name)) {} explicit Cat(std::string name) : Pet(std::move(name)) {}
}; };
py::class_<pets::Pet>(m, "Pet", py::module_local()) py::class_<pets::Pet>(m, "Pet", py::module_local())
.def("get_name", &pets::Pet::name); .def("get_name", &pets::Pet::name);
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import local_bindings as m from pybind11_tests import local_bindings as m
......
...@@ -19,9 +19,9 @@ using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>; ...@@ -19,9 +19,9 @@ using overload_cast_ = pybind11::detail::overload_cast_impl<Args...>;
class ExampleMandA { class ExampleMandA {
public: public:
ExampleMandA() { print_default_created(this); } ExampleMandA() { print_default_created(this); }
ExampleMandA(int value) : value(value) { print_created(this, value); } explicit ExampleMandA(int value) : value(value) { print_created(this, value); }
ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); } ExampleMandA(const ExampleMandA &e) : value(e.value) { print_copy_created(this); }
ExampleMandA(std::string&&) {} explicit ExampleMandA(std::string &&) {}
ExampleMandA(ExampleMandA &&e) noexcept : value(e.value) { print_move_created(this); } ExampleMandA(ExampleMandA &&e) noexcept : value(e.value) { print_move_created(this); }
~ExampleMandA() { print_destroyed(this); } ~ExampleMandA() { print_destroyed(this); }
...@@ -124,14 +124,14 @@ class NoneCastTester { ...@@ -124,14 +124,14 @@ class NoneCastTester {
public: public:
int answer = -1; int answer = -1;
NoneCastTester() = default; NoneCastTester() = default;
NoneCastTester(int v) : answer(v) {} explicit NoneCastTester(int v) : answer(v) {}
}; };
struct StrIssue { struct StrIssue {
int val = -1; int val = -1;
StrIssue() = default; StrIssue() = default;
StrIssue(int i) : val{i} {} explicit StrIssue(int i) : val{i} {}
}; };
// Issues #854, #910: incompatible function args when member function/pointer is in unregistered base class // Issues #854, #910: incompatible function args when member function/pointer is in unregistered base class
......
...@@ -2,9 +2,8 @@ ...@@ -2,9 +2,8 @@
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import methods_and_attributes as m
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import methods_and_attributes as m
def test_methods_and_attributes(): def test_methods_and_attributes():
......
...@@ -20,7 +20,7 @@ TEST_SUBMODULE(modules, m) { ...@@ -20,7 +20,7 @@ TEST_SUBMODULE(modules, m) {
// test_reference_internal // test_reference_internal
class A { class A {
public: public:
A(int v) : v(v) { print_created(this, v); } explicit A(int v) : v(v) { print_created(this, v); }
~A() { print_destroyed(this); } ~A() { print_destroyed(this); }
A(const A&) { print_copy_created(this); } A(const A&) { print_copy_created(this); }
A& operator=(const A &copy) { print_copy_assigned(this); v = copy.v; return *this; } A& operator=(const A &copy) { print_copy_assigned(this); v = copy.v; return *this; }
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from pybind11_tests import ConstructorStats
from pybind11_tests import modules as m from pybind11_tests import modules as m
from pybind11_tests.modules import subsubmodule as ms from pybind11_tests.modules import subsubmodule as ms
from pybind11_tests import ConstructorStats
def test_nested_modules(): def test_nested_modules():
...@@ -54,18 +54,20 @@ def test_reference_internal(): ...@@ -54,18 +54,20 @@ def test_reference_internal():
def test_importing(): def test_importing():
from pybind11_tests.modules import OD
from collections import OrderedDict from collections import OrderedDict
from pybind11_tests.modules import OD
assert OD is OrderedDict assert OD is OrderedDict
assert str(OD([(1, "a"), (2, "b")])) == "OrderedDict([(1, 'a'), (2, 'b')])" assert str(OD([(1, "a"), (2, "b")])) == "OrderedDict([(1, 'a'), (2, 'b')])"
def test_pydoc(): def test_pydoc():
"""Pydoc needs to be able to provide help() for everything inside a pybind11 module""" """Pydoc needs to be able to provide help() for everything inside a pybind11 module"""
import pybind11_tests
import pydoc import pydoc
import pybind11_tests
assert pybind11_tests.__name__ == "pybind11_tests" assert pybind11_tests.__name__ == "pybind11_tests"
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)
......
...@@ -16,7 +16,7 @@ namespace { ...@@ -16,7 +16,7 @@ namespace {
// Many bases for testing that multiple inheritance from many classes (i.e. requiring extra // Many bases for testing that multiple inheritance from many classes (i.e. requiring extra
// space for holder constructed flags) works. // space for holder constructed flags) works.
template <int N> struct BaseN { template <int N> struct BaseN {
BaseN(int i) : i(i) { } explicit BaseN(int i) : i(i) {}
int i; int i;
}; };
...@@ -47,12 +47,12 @@ int VanillaStaticMix2::static_value = 12; ...@@ -47,12 +47,12 @@ int VanillaStaticMix2::static_value = 12;
// test_multiple_inheritance_virtbase // test_multiple_inheritance_virtbase
struct Base1a { struct Base1a {
Base1a(int i) : i(i) { } explicit Base1a(int i) : i(i) {}
int foo() const { return i; } int foo() const { return i; }
int i; int i;
}; };
struct Base2a { struct Base2a {
Base2a(int i) : i(i) { } explicit Base2a(int i) : i(i) {}
int bar() const { return i; } int bar() const { return i; }
int i; int i;
}; };
...@@ -77,7 +77,7 @@ TEST_SUBMODULE(multiple_inheritance, m) { ...@@ -77,7 +77,7 @@ TEST_SUBMODULE(multiple_inheritance, m) {
// test_multiple_inheritance_mix1 // test_multiple_inheritance_mix1
// test_multiple_inheritance_mix2 // test_multiple_inheritance_mix2
struct Base1 { struct Base1 {
Base1(int i) : i(i) { } explicit Base1(int i) : i(i) {}
int foo() const { return i; } int foo() const { return i; }
int i; int i;
}; };
...@@ -86,7 +86,7 @@ TEST_SUBMODULE(multiple_inheritance, m) { ...@@ -86,7 +86,7 @@ TEST_SUBMODULE(multiple_inheritance, m) {
.def("foo", &Base1::foo); .def("foo", &Base1::foo);
struct Base2 { struct Base2 {
Base2(int i) : i(i) { } explicit Base2(int i) : i(i) {}
int bar() const { return i; } int bar() const { return i; }
int i; int i;
}; };
...@@ -108,7 +108,10 @@ TEST_SUBMODULE(multiple_inheritance, m) { ...@@ -108,7 +108,10 @@ TEST_SUBMODULE(multiple_inheritance, m) {
// test_multiple_inheritance_python_many_bases // test_multiple_inheritance_python_many_bases
#define PYBIND11_BASEN(N) py::class_<BaseN<N>>(m, "BaseN" #N).def(py::init<int>()).def("f" #N, [](BaseN<N> &b) { return b.i + N; }) #define PYBIND11_BASEN(N) \
py::class_<BaseN<(N)>>(m, "BaseN" #N).def(py::init<int>()).def("f" #N, [](BaseN<N> &b) { \
return b.i + (N); \
})
PYBIND11_BASEN( 1); PYBIND11_BASEN( 2); PYBIND11_BASEN( 3); PYBIND11_BASEN( 4); PYBIND11_BASEN( 1); PYBIND11_BASEN( 2); PYBIND11_BASEN( 3); PYBIND11_BASEN( 4);
PYBIND11_BASEN( 5); PYBIND11_BASEN( 6); PYBIND11_BASEN( 7); PYBIND11_BASEN( 8); PYBIND11_BASEN( 5); PYBIND11_BASEN( 6); PYBIND11_BASEN( 7); PYBIND11_BASEN( 8);
PYBIND11_BASEN( 9); PYBIND11_BASEN(10); PYBIND11_BASEN(11); PYBIND11_BASEN(12); PYBIND11_BASEN( 9); PYBIND11_BASEN(10); PYBIND11_BASEN(11); PYBIND11_BASEN(12);
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import ConstructorStats from pybind11_tests import ConstructorStats
from pybind11_tests import multiple_inheritance as m from pybind11_tests import multiple_inheritance as m
......
...@@ -405,6 +405,16 @@ TEST_SUBMODULE(numpy_array, sm) { ...@@ -405,6 +405,16 @@ TEST_SUBMODULE(numpy_array, sm) {
return a; return a;
}); });
sm.def("array_view",
[](py::array_t<uint8_t> a, const std::string &dtype) { return a.view(dtype); });
sm.def("reshape_initializer_list", [](py::array_t<int> a, size_t N, size_t M, size_t O) {
return a.reshape({N, M, O});
});
sm.def("reshape_tuple", [](py::array_t<int> a, const std::vector<int> &new_shape) {
return a.reshape(new_shape);
});
sm.def("index_using_ellipsis", sm.def("index_using_ellipsis",
[](const py::array &a) { return a[py::make_tuple(0, py::ellipsis(), 0)]; }); [](const py::array &a) { return a[py::make_tuple(0, py::ellipsis(), 0)]; });
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import numpy_array as m from pybind11_tests import numpy_array as m
np = pytest.importorskip("numpy") np = pytest.importorskip("numpy")
...@@ -412,7 +411,7 @@ def test_array_unchecked_fixed_dims(msg): ...@@ -412,7 +411,7 @@ def test_array_unchecked_fixed_dims(msg):
assert m.proxy_auxiliaries2_const_ref(z1) assert m.proxy_auxiliaries2_const_ref(z1)
def test_array_unchecked_dyn_dims(msg): def test_array_unchecked_dyn_dims():
z1 = np.array([[1, 2], [3, 4]], dtype="float64") z1 = np.array([[1, 2], [3, 4]], dtype="float64")
m.proxy_add2_dyn(z1, 10) m.proxy_add2_dyn(z1, 10)
assert np.all(z1 == [[11, 12], [13, 14]]) assert np.all(z1 == [[11, 12], [13, 14]])
...@@ -445,7 +444,7 @@ def test_initializer_list(): ...@@ -445,7 +444,7 @@ def test_initializer_list():
assert m.array_initializer_list4().shape == (1, 2, 3, 4) assert m.array_initializer_list4().shape == (1, 2, 3, 4)
def test_array_resize(msg): def test_array_resize():
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype="float64") a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype="float64")
m.array_reshape2(a) m.array_reshape2(a)
assert a.size == 9 assert a.size == 9
...@@ -471,12 +470,52 @@ def test_array_resize(msg): ...@@ -471,12 +470,52 @@ def test_array_resize(msg):
@pytest.mark.xfail("env.PYPY") @pytest.mark.xfail("env.PYPY")
def test_array_create_and_resize(msg): def test_array_create_and_resize():
a = m.create_and_resize(2) a = m.create_and_resize(2)
assert a.size == 4 assert a.size == 4
assert np.all(a == 42.0) assert np.all(a == 42.0)
def test_array_view():
a = np.ones(100 * 4).astype("uint8")
a_float_view = m.array_view(a, "float32")
assert a_float_view.shape == (100 * 1,) # 1 / 4 bytes = 8 / 32
a_int16_view = m.array_view(a, "int16") # 1 / 2 bytes = 16 / 32
assert a_int16_view.shape == (100 * 2,)
def test_array_view_invalid():
a = np.ones(100 * 4).astype("uint8")
with pytest.raises(TypeError):
m.array_view(a, "deadly_dtype")
def test_reshape_initializer_list():
a = np.arange(2 * 7 * 3) + 1
x = m.reshape_initializer_list(a, 2, 7, 3)
assert x.shape == (2, 7, 3)
assert list(x[1][4]) == [34, 35, 36]
with pytest.raises(ValueError) as excinfo:
m.reshape_initializer_list(a, 1, 7, 3)
assert str(excinfo.value) == "cannot reshape array of size 42 into shape (1,7,3)"
def test_reshape_tuple():
a = np.arange(3 * 7 * 2) + 1
x = m.reshape_tuple(a, (3, 7, 2))
assert x.shape == (3, 7, 2)
assert list(x[1][4]) == [23, 24]
y = m.reshape_tuple(x, (x.size,))
assert y.shape == (42,)
with pytest.raises(ValueError) as excinfo:
m.reshape_tuple(a, (3, 7, 1))
assert str(excinfo.value) == "cannot reshape array of size 42 into shape (3,7,1)"
with pytest.raises(ValueError) as excinfo:
m.reshape_tuple(a, ())
assert str(excinfo.value) == "cannot reshape array of size 42 into shape ()"
def test_index_using_ellipsis(): def test_index_using_ellipsis():
a = m.index_using_ellipsis(np.zeros((5, 6, 7))) a = m.index_using_ellipsis(np.zeros((5, 6, 7)))
assert a.shape == (6,) assert a.shape == (6,)
......
...@@ -148,11 +148,13 @@ py::array mkarray_via_buffer(size_t n) { ...@@ -148,11 +148,13 @@ py::array mkarray_via_buffer(size_t n) {
1, { n }, { sizeof(T) })); 1, { n }, { sizeof(T) }));
} }
#define SET_TEST_VALS(s, i) do { \ #define SET_TEST_VALS(s, i) \
s.bool_ = (i) % 2 != 0; \ do { \
s.uint_ = (uint32_t) (i); \ (s).bool_ = (i) % 2 != 0; \
s.float_ = (float) (i) * 1.5f; \ (s).uint_ = (uint32_t) (i); \
s.ldbl_ = (long double) (i) * -2.5L; } while (0) (s).float_ = (float) (i) *1.5f; \
(s).ldbl_ = (long double) (i) * -2.5L; \
} while (0)
template <typename S> template <typename S>
py::array_t<S, 0> create_recarray(size_t n) { py::array_t<S, 0> create_recarray(size_t n) {
......
...@@ -4,7 +4,6 @@ import re ...@@ -4,7 +4,6 @@ import re
import pytest import pytest
import env # noqa: F401 import env # noqa: F401
from pybind11_tests import numpy_dtypes as m from pybind11_tests import numpy_dtypes as m
np = pytest.importorskip("numpy") np = pytest.importorskip("numpy")
...@@ -64,14 +63,20 @@ def partial_ld_offset(): ...@@ -64,14 +63,20 @@ def partial_ld_offset():
def partial_dtype_fmt(): def partial_dtype_fmt():
ld = np.dtype("longdouble") ld = np.dtype("longdouble")
partial_ld_off = partial_ld_offset() partial_ld_off = partial_ld_offset()
return dt_fmt().format(ld.itemsize, partial_ld_off, partial_ld_off + ld.itemsize) partial_size = partial_ld_off + ld.itemsize
partial_end_padding = partial_size % np.dtype("uint64").alignment
return dt_fmt().format(
ld.itemsize, partial_ld_off, partial_size + partial_end_padding
)
def partial_nested_fmt(): def partial_nested_fmt():
ld = np.dtype("longdouble") ld = np.dtype("longdouble")
partial_nested_off = 8 + 8 * (ld.alignment > 8) partial_nested_off = 8 + 8 * (ld.alignment > 8)
partial_ld_off = partial_ld_offset() partial_ld_off = partial_ld_offset()
partial_nested_size = partial_nested_off * 2 + partial_ld_off + ld.itemsize partial_size = partial_ld_off + ld.itemsize
partial_end_padding = partial_size % np.dtype("uint64").alignment
partial_nested_size = partial_nested_off * 2 + partial_size + partial_end_padding
return "{{'names':['a'], 'formats':[{}], 'offsets':[{}], 'itemsize':{}}}".format( return "{{'names':['a'], 'formats':[{}], 'offsets':[{}], 'itemsize':{}}}".format(
partial_dtype_fmt(), partial_nested_off, partial_nested_size partial_dtype_fmt(), partial_nested_off, partial_nested_size
) )
...@@ -92,10 +97,12 @@ def test_format_descriptors(): ...@@ -92,10 +97,12 @@ def test_format_descriptors():
ldbl_fmt = ("4x" if ld.alignment > 4 else "") + ld.char ldbl_fmt = ("4x" if ld.alignment > 4 else "") + ld.char
ss_fmt = "^T{?:bool_:3xI:uint_:f:float_:" + ldbl_fmt + ":ldbl_:}" ss_fmt = "^T{?:bool_:3xI:uint_:f:float_:" + ldbl_fmt + ":ldbl_:}"
dbl = np.dtype("double") dbl = np.dtype("double")
end_padding = ld.itemsize % np.dtype("uint64").alignment
partial_fmt = ( partial_fmt = (
"^T{?:bool_:3xI:uint_:f:float_:" "^T{?:bool_:3xI:uint_:f:float_:"
+ str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8)) + str(4 * (dbl.alignment > 4) + dbl.itemsize + 8 * (ld.alignment > 8))
+ "xg:ldbl_:}" + "xg:ldbl_:"
+ (str(end_padding) + "x}" if end_padding > 0 else "}")
) )
nested_extra = str(max(8, ld.alignment)) nested_extra = str(max(8, ld.alignment))
assert m.print_format_descriptors() == [ assert m.print_format_descriptors() == [
......
...@@ -52,7 +52,7 @@ TEST_SUBMODULE(numpy_vectorize, m) { ...@@ -52,7 +52,7 @@ TEST_SUBMODULE(numpy_vectorize, m) {
// Passthrough test: references and non-pod types should be automatically passed through (in the // Passthrough test: references and non-pod types should be automatically passed through (in the
// function definition below, only `b`, `d`, and `g` are vectorized): // function definition below, only `b`, `d`, and `g` are vectorized):
struct NonPODClass { struct NonPODClass {
NonPODClass(int v) : value{v} {} explicit NonPODClass(int v) : value{v} {}
int value; int value;
}; };
py::class_<NonPODClass>(m, "NonPODClass") py::class_<NonPODClass>(m, "NonPODClass")
...@@ -71,7 +71,7 @@ TEST_SUBMODULE(numpy_vectorize, m) { ...@@ -71,7 +71,7 @@ TEST_SUBMODULE(numpy_vectorize, m) {
// test_method_vectorization // test_method_vectorization
struct VectorizeTestClass { struct VectorizeTestClass {
VectorizeTestClass(int v) : value{v} {}; explicit VectorizeTestClass(int v) : value{v} {};
float method(int x, float y) const { return y + (float) (x + value); } float method(int x, float y) const { return y + (float) (x + value); }
int value = 0; int value = 0;
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment