Skip to content

Commit

Permalink
Add a (failing) tests for issue #1064
Browse files Browse the repository at this point in the history
  • Loading branch information
mvaled committed Aug 1, 2020
1 parent 51171f7 commit 0d727c7
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ macros = ["ctor", "indoc", "inventory", "paste", "pyo3cls", "unindent"]
# Optimizes PyObject to Vec conversion and so on.
nightly = []

no-return-notimplemented = []

# this is no longer needed internally, but setuptools-rust assumes this feature
python3 = []

Expand Down
127 changes: 127 additions & 0 deletions tests/test_arithmetics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -423,3 +423,130 @@ fn rich_comparisons_python_3_type_error() {
py_expect_exception!(py, c2, "c2 >= 1", PyTypeError);
py_expect_exception!(py, c2, "1 >= c2", PyTypeError);
}

#[cfg(not(feature = "no-return-notimplemented"))]
#[cfg(test)]
mod not_implemented {
use super::*;

#[pyclass]
struct RichComparisonToSelf {}

#[pyproto]
impl<'p> PyObjectProtocol<'p> for RichComparisonToSelf {
fn __repr__(&self) -> &'static str {
"RC_Self"
}

fn __richcmp__(&self, other: PyRef<'p, Self>, _op: CompareOp) -> PyObject {
other.py().None()
}
}

fn test_dunder(operator: &str) {
let gil = Python::acquire_gil();
let py = gil.python();
let c2 = PyCell::new(py, RichComparisonToSelf {}).unwrap();
py_run!(
py,
c2,
&format!(
"\
class Other:
def __eq__(self, other):
return True
__ne__ = __lt__ = __le__ = __gt__ = __ge__ = __eq__
def __radd__(self, other):
return self
___rsub__ = __rmul__ = __rtruediv__ = __rfloordiv__ = __radd__
___rmatmul__ = __rlshift__ = __rrshift__ = __rmod__ = __radd__
c2 {} Other()",
operator
)
);
py_expect_exception!(
py,
c2,
&format!("class Other: pass; c2 {} Other()", operator),
PyTypeError
);
}

macro_rules! not_implemented_test {
($dunder: ident, $operator: literal) => {
#[test]
fn $dunder() {
test_dunder($operator)
}
};

[$( ($dunder: ident, $operator: literal) ),*] => {
$(not_implemented_test!{$dunder, $operator})*
};

[$( ($dunder: ident, $operator: literal) ),* ,] => {
$(not_implemented_test!{$dunder, $operator})*
};

}

mod richcmp {
use super::*;

not_implemented_test![
(eq, "=="),
(ne, "!="),
(lt, "<"),
(le, "<="),
(gt, ">"),
(ge, ">="),
];
}

#[cfg(feature = "remove-this-when-implemented")]
mod reversed {
use super::*;

// The pyclass returns NotImplemented, so the other object gets is
// reversed dunder method called.
not_implemented_test![
(rand, "&"),
(ror, "|"),
(rxor, "^"),
(radd, "+"),
(rsub, "-"),
(rmul, "*"),
(rmatmul, "@"),
(rtruediv, "/"),
(rfloordiv, "//"),
(rmod, "%"),
(rpow, "**"),
(rlshift, "<<"),
(rshift, ">>"),
];
}

#[cfg(feature = "remove-this-when-implemented")]
mod inplace {
use super::*;

// The pyclass returns NotImplemented for the in-place operator, so the
// other object gets is reversed dunder method called.
not_implemented_test![
(rand, "&="),
(ror, "|="),
(rxor, "^="),
(radd, "+="),
(rsub, "-="),
(rmul, "*="),
(rmatmul, "@="),
(rtruediv, "/="),
(rfloordiv, "//="),
(rmod, "%="),
(rpow, "**="),
(rlshift, "<<="),
(rshift, ">>="),
];
}
}

0 comments on commit 0d727c7

Please sign in to comment.