Skip to content

Fix Eigen argument doc strings #791

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 16 additions & 15 deletions include/pybind11/eigen.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,20 +179,21 @@ template <typename Type_> struct EigenProps {
constexpr bool show_c_contiguous = show_order && requires_row_major;
constexpr bool show_f_contiguous = !show_c_contiguous && show_order && requires_col_major;

return _("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
_("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) +
_(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) +
_("]") +
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be
// satisfied: writeable=True (for a mutable reference), and, depending on the map's stride
// options, possibly f_contiguous or c_contiguous. We include them in the descriptor output
// to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to
// see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you
// *gave* a numpy.ndarray of the right type and dimensions.
_<show_writeable>(", flags.writeable", "") +
_<show_c_contiguous>(", flags.c_contiguous", "") +
_<show_f_contiguous>(", flags.f_contiguous", "") +
_("]");
return type_descr(_("numpy.ndarray[") + npy_format_descriptor<Scalar>::name() +
_("[") + _<fixed_rows>(_<(size_t) rows>(), _("m")) +
_(", ") + _<fixed_cols>(_<(size_t) cols>(), _("n")) +
_("]") +
// For a reference type (e.g. Ref<MatrixXd>) we have other constraints that might need to be
// satisfied: writeable=True (for a mutable reference), and, depending on the map's stride
// options, possibly f_contiguous or c_contiguous. We include them in the descriptor output
// to provide some hint as to why a TypeError is occurring (otherwise it can be confusing to
// see that a function accepts a 'numpy.ndarray[float64[3,2]]' and an error message that you
// *gave* a numpy.ndarray of the right type and dimensions.
_<show_writeable>(", flags.writeable", "") +
_<show_c_contiguous>(", flags.c_contiguous", "") +
_<show_f_contiguous>(", flags.f_contiguous", "") +
_("]")
);
}
};

Expand Down Expand Up @@ -318,7 +319,7 @@ struct type_caster<Type, enable_if_t<is_eigen_dense_plain<Type>::value>> {
return cast_impl(src, policy, parent);
}

static PYBIND11_DESCR name() { return type_descr(props::descriptor()); }
static PYBIND11_DESCR name() { return props::descriptor(); }

operator Type*() { return &value; }
operator Type&() { return value; }
Expand Down
7 changes: 7 additions & 0 deletions tests/test_eigen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,13 @@ test_initializer eigen([](py::module &m) {
m.def("iss738_f1", &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>, py::arg().noconvert());
m.def("iss738_f2", &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>, py::arg().noconvert());

// Make sure named arguments are working properly:
m.def("matrix_multiply", [](const py::EigenDRef<const Eigen::MatrixXd> A, const py::EigenDRef<const Eigen::MatrixXd> B)
-> Eigen::MatrixXd {
if (A.cols() != B.rows()) throw std::domain_error("Nonconformable matrices!");
return A * B;
}, py::arg("A"), py::arg("B"));

py::class_<CustomOperatorNew>(m, "CustomOperatorNew")
.def(py::init<>())
.def_readonly("a", &CustomOperatorNew::a)
Expand Down
29 changes: 26 additions & 3 deletions tests/test_eigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,15 @@ def test_mutator_descriptors():
fixed_mutator_a(zc)
with pytest.raises(TypeError) as excinfo:
fixed_mutator_r(zc)
assert ('(numpy.ndarray[float32[5, 6], flags.writeable, flags.c_contiguous]) -> arg0: None'
assert ('(arg0: numpy.ndarray[float32[5, 6], flags.writeable, flags.c_contiguous]) -> None'
in str(excinfo.value))
with pytest.raises(TypeError) as excinfo:
fixed_mutator_c(zr)
assert ('(numpy.ndarray[float32[5, 6], flags.writeable, flags.f_contiguous]) -> arg0: None'
assert ('(arg0: numpy.ndarray[float32[5, 6], flags.writeable, flags.f_contiguous]) -> None'
in str(excinfo.value))
with pytest.raises(TypeError) as excinfo:
fixed_mutator_a(np.array([[1, 2], [3, 4]], dtype='float32'))
assert ('(numpy.ndarray[float32[5, 6], flags.writeable]) -> arg0: None'
assert ('(arg0: numpy.ndarray[float32[5, 6], flags.writeable]) -> None'
in str(excinfo.value))
zr.flags.writeable = False
with pytest.raises(TypeError):
Expand Down Expand Up @@ -582,6 +582,29 @@ def test_dense_signature(doc):
"""


def test_named_arguments():
from pybind11_tests import matrix_multiply

a = np.array([[1.0, 2], [3, 4], [5, 6]])
b = np.ones((2, 1))

assert np.all(matrix_multiply(a, b) == np.array([[3.], [7], [11]]))
assert np.all(matrix_multiply(A=a, B=b) == np.array([[3.], [7], [11]]))
assert np.all(matrix_multiply(B=b, A=a) == np.array([[3.], [7], [11]]))

with pytest.raises(ValueError) as excinfo:
matrix_multiply(b, a)
assert str(excinfo.value) == 'Nonconformable matrices!'

with pytest.raises(ValueError) as excinfo:
matrix_multiply(A=b, B=a)
assert str(excinfo.value) == 'Nonconformable matrices!'

with pytest.raises(ValueError) as excinfo:
matrix_multiply(B=a, A=b)
assert str(excinfo.value) == 'Nonconformable matrices!'


@pytest.requires_eigen_and_scipy
def test_sparse():
from pybind11_tests import sparse_r, sparse_c, sparse_copy_r, sparse_copy_c
Expand Down