1 use cpython::{PyDict, PyObject, PyResult, PyTuple, Python}; |
1 use cpython::exc::ValueError; |
|
2 use cpython::{PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple, Python}; |
|
3 use hg::revlog::Node; |
|
4 use std::convert::TryFrom; |
2 |
5 |
3 #[allow(unused)] |
6 #[allow(unused)] |
4 pub fn print_python_trace(py: Python) -> PyResult<PyObject> { |
7 pub fn print_python_trace(py: Python) -> PyResult<PyObject> { |
5 eprintln!("==============================="); |
8 eprintln!("==============================="); |
6 eprintln!("Printing Python stack from Rust"); |
9 eprintln!("Printing Python stack from Rust"); |
9 let sys = py.import("sys")?; |
12 let sys = py.import("sys")?; |
10 let kwargs = PyDict::new(py); |
13 let kwargs = PyDict::new(py); |
11 kwargs.set_item(py, "file", sys.get(py, "stderr")?)?; |
14 kwargs.set_item(py, "file", sys.get(py, "stderr")?)?; |
12 traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) |
15 traceback.call(py, "print_stack", PyTuple::new(py, &[]), Some(&kwargs)) |
13 } |
16 } |
|
17 |
|
18 // Necessary evil for the time being, could maybe be moved to |
|
19 // a TryFrom in Node itself |
|
20 const NODE_BYTES_LENGTH: usize = 20; |
|
21 type NodeData = [u8; NODE_BYTES_LENGTH]; |
|
22 |
|
23 /// Copy incoming Python bytes given as `PyObject` into `Node`, |
|
24 /// doing the necessary checks |
|
25 pub fn node_from_py_object<'a>( |
|
26 py: Python, |
|
27 bytes: &'a PyObject, |
|
28 ) -> PyResult<Node> { |
|
29 let as_py_bytes: &'a PyBytes = bytes.extract(py)?; |
|
30 node_from_py_bytes(py, as_py_bytes) |
|
31 } |
|
32 |
|
33 /// Clone incoming Python bytes given as `PyBytes` as a `Node`, |
|
34 /// doing the necessary checks. |
|
35 pub fn node_from_py_bytes<'a>( |
|
36 py: Python, |
|
37 bytes: &'a PyBytes, |
|
38 ) -> PyResult<Node> { |
|
39 <NodeData>::try_from(bytes.data(py)) |
|
40 .map_err(|_| { |
|
41 PyErr::new::<ValueError, _>( |
|
42 py, |
|
43 format!("{}-byte hash required", NODE_BYTES_LENGTH), |
|
44 ) |
|
45 }) |
|
46 .map(|n| n.into()) |
|
47 } |