|
1 |
| -use cpython::{PyObject, PyResult}; |
| 1 | +use cpython::{PyObject, PyErr, PyResult, PyTuple, ToPyObject, PythonObject}; |
2 | 2 | use lumol;
|
| 3 | +use lumol::Vector3D; |
3 | 4 | use std::cell::RefCell;
|
4 | 5 |
|
| 6 | +use LumolError; |
| 7 | + |
5 | 8 | register!(|py, m| {
|
6 | 9 | try!(m.add_class::<Particle>(py));
|
7 | 10 | Ok(())
|
@@ -39,6 +42,72 @@ py_class!(class Particle |py| {
|
39 | 42 | self.particle(py).borrow_mut().charge = charge;
|
40 | 43 | Ok(py.None())
|
41 | 44 | }
|
| 45 | + |
| 46 | + def position(&self) -> PyResult<PyTuple> { |
| 47 | + let position = &self.particle(py).borrow().position; |
| 48 | + |
| 49 | + let x = position[0].to_py_object(py).into_object(); |
| 50 | + let y = position[1].to_py_object(py).into_object(); |
| 51 | + let z = position[2].to_py_object(py).into_object(); |
| 52 | + |
| 53 | + Ok(PyTuple::new(py, &[x, y, z])) |
| 54 | + } |
| 55 | + |
| 56 | + def set_position(&self, position: &PyTuple) -> PyResult<PyObject> { |
| 57 | + if position.len(py) != 3 { |
| 58 | + return raise!(py, format!( |
| 59 | + "Wrong size for the position: should be a 3-dimmensional \ |
| 60 | + tuple, but contains {} elements", position.len(py) |
| 61 | + )); |
| 62 | + } |
| 63 | + |
| 64 | + let x = try!(position.get_item(py, 0).extract::<f64>(py).or( |
| 65 | + raise!(py, "Position elements should be numbers")) |
| 66 | + ); |
| 67 | + let y = try!(position.get_item(py, 1).extract::<f64>(py).or( |
| 68 | + raise!(py, "Position elements should be numbers")) |
| 69 | + ); |
| 70 | + let z = try!(position.get_item(py, 2).extract::<f64>(py).or( |
| 71 | + raise!(py, "Position elements should be numbers")) |
| 72 | + ); |
| 73 | + |
| 74 | + self.particle(py).borrow_mut().position = Vector3D::new(x, y, z); |
| 75 | + |
| 76 | + Ok(py.None()) |
| 77 | + } |
| 78 | + |
| 79 | + def velocity(&self) -> PyResult<PyTuple> { |
| 80 | + let velocity = &self.particle(py).borrow().velocity; |
| 81 | + |
| 82 | + let x = velocity[0].to_py_object(py).into_object(); |
| 83 | + let y = velocity[1].to_py_object(py).into_object(); |
| 84 | + let z = velocity[2].to_py_object(py).into_object(); |
| 85 | + |
| 86 | + Ok(PyTuple::new(py, &[x, y, z])) |
| 87 | + } |
| 88 | + |
| 89 | + def set_velocity(&self, velocity: &PyTuple) -> PyResult<PyObject> { |
| 90 | + if velocity.len(py) != 3 { |
| 91 | + return raise!(py, format!( |
| 92 | + "Wrong size for the velocity: should be a 3-dimmensional \ |
| 93 | + tuple, but contains {} elements", velocity.len(py) |
| 94 | + )); |
| 95 | + } |
| 96 | + |
| 97 | + let x = try!(velocity.get_item(py, 0).extract::<f64>(py).or( |
| 98 | + raise!(py, "Velocity elements should be numbers")) |
| 99 | + ); |
| 100 | + let y = try!(velocity.get_item(py, 1).extract::<f64>(py).or( |
| 101 | + raise!(py, "Velocity elements should be numbers")) |
| 102 | + ); |
| 103 | + let z = try!(velocity.get_item(py, 2).extract::<f64>(py).or( |
| 104 | + raise!(py, "Velocity elements should be numbers")) |
| 105 | + ); |
| 106 | + |
| 107 | + self.particle(py).borrow_mut().velocity = Vector3D::new(x, y, z); |
| 108 | + |
| 109 | + Ok(py.None()) |
| 110 | + } |
42 | 111 | });
|
43 | 112 |
|
44 | 113 | #[cfg(test)]
|
@@ -120,5 +189,41 @@ mod tests {
|
120 | 189 | "assert particle.charge() == 2"
|
121 | 190 | );
|
122 | 191 | }
|
| 192 | + |
| 193 | + #[test] |
| 194 | + fn position() { |
| 195 | + let gil = Python::acquire_gil(); |
| 196 | + let py = gil.python(); |
| 197 | + let particle = create_instance!(py, Particle, ("He",)); |
| 198 | + |
| 199 | + py_run_with!(py, particle; |
| 200 | + "assert particle.position() == (0.0, 0.0, 0.0)", |
| 201 | + "particle.set_position((1, 2, 3))", |
| 202 | + "assert particle.position() == (1, 2, 3)", |
| 203 | + "assert_raises(particle.set_position, (2, 3))", |
| 204 | + "assert_raises(particle.set_position, (1, 2, 3, 4))", |
| 205 | + "assert_raises(particle.set_position, ('1', 2, 3))", |
| 206 | + "assert_raises(particle.set_position, (1, '2', 3))", |
| 207 | + "assert_raises(particle.set_position, (1, 2, '3'))", |
| 208 | + ); |
| 209 | + } |
| 210 | + |
| 211 | + #[test] |
| 212 | + fn velocity() { |
| 213 | + let gil = Python::acquire_gil(); |
| 214 | + let py = gil.python(); |
| 215 | + let particle = create_instance!(py, Particle, ("He",)); |
| 216 | + |
| 217 | + py_run_with!(py, particle; |
| 218 | + "assert particle.velocity() == (0.0, 0.0, 0.0)", |
| 219 | + "particle.set_velocity((1, 2, 3))", |
| 220 | + "assert particle.velocity() == (1, 2, 3)", |
| 221 | + "assert_raises(particle.set_velocity, (2, 3))", |
| 222 | + "assert_raises(particle.set_velocity, (1, 2, 3, 4))", |
| 223 | + "assert_raises(particle.set_velocity, ('1', 2, 3))", |
| 224 | + "assert_raises(particle.set_velocity, (1, '2', 3))", |
| 225 | + "assert_raises(particle.set_velocity, (1, 2, '3'))", |
| 226 | + ); |
| 227 | + } |
123 | 228 | }
|
124 | 229 | }
|
0 commit comments