rust/hg-cpython/src/utils.rs
branchstable
changeset 52213 96b113d22b34
parent 52185 e698e3e75420
equal deleted inserted replaced
52212:fa58f4f97337 52213:96b113d22b34
     1 use cpython::exc::ValueError;
     1 use cpython::exc::{KeyboardInterrupt, ValueError};
     2 use cpython::{
     2 use cpython::{
     3     ObjectProtocol, PyBytes, PyDict, PyErr, PyObject, PyResult, PyTuple,
     3     ObjectProtocol, PyBytes, PyClone, PyDict, PyErr, PyObject, PyResult,
     4     Python, ToPyObject,
     4     PyTuple, Python, ToPyObject,
     5 };
     5 };
     6 use hg::config::Config;
     6 use hg::config::Config;
     7 use hg::errors::HgError;
     7 use hg::errors::HgError;
     8 use hg::repo::{Repo, RepoError};
     8 use hg::repo::{Repo, RepoError};
     9 use hg::revlog::Node;
     9 use hg::revlog::Node;
    47                 .unwrap();
    47                 .unwrap();
    48             PyErr::from_instance(
    48             PyErr::from_instance(
    49                 py,
    49                 py,
    50                 cls.call(py, (msg,), None).ok().into_py_object(py),
    50                 cls.call(py, (msg,), None).ok().into_py_object(py),
    51             )
    51             )
       
    52         }
       
    53         HgError::InterruptReceived => {
       
    54             PyErr::new::<KeyboardInterrupt, _>(py, "")
    52         }
    55         }
    53         e => PyErr::new::<cpython::exc::RuntimeError, _>(py, e.to_string()),
    56         e => PyErr::new::<cpython::exc::RuntimeError, _>(py, e.to_string()),
    54     })
    57     })
    55 }
    58 }
    56 
    59 
   102                 format!("{}-byte hash required", NODE_BYTES_LENGTH),
   105                 format!("{}-byte hash required", NODE_BYTES_LENGTH),
   103             )
   106             )
   104         })
   107         })
   105         .map(Into::into)
   108         .map(Into::into)
   106 }
   109 }
       
   110 
       
   111 /// Wrap a call to `func` so that Python's `SIGINT` handler is first stored,
       
   112 /// then restored after the call to `func` and finally raised if
       
   113 /// `func` returns a [`HgError::InterruptReceived`]
       
   114 pub fn with_sigint_wrapper<R>(
       
   115     py: Python,
       
   116     func: impl Fn() -> Result<R, HgError>,
       
   117 ) -> PyResult<Result<R, HgError>> {
       
   118     let signal_py_mod = py.import("signal")?;
       
   119     let sigint_py_const = signal_py_mod.get(py, "SIGINT")?;
       
   120     let old_handler = signal_py_mod.call(
       
   121         py,
       
   122         "getsignal",
       
   123         PyTuple::new(py, &[sigint_py_const.clone_ref(py)]),
       
   124         None,
       
   125     )?;
       
   126     let res = func();
       
   127     // Reset the old signal handler in Python because we've may have changed it
       
   128     signal_py_mod.call(
       
   129         py,
       
   130         "signal",
       
   131         PyTuple::new(py, &[sigint_py_const.clone_ref(py), old_handler]),
       
   132         None,
       
   133     )?;
       
   134     if let Err(HgError::InterruptReceived) = res {
       
   135         // Trigger the signal in Python
       
   136         signal_py_mod.call(
       
   137             py,
       
   138             "raise_signal",
       
   139             PyTuple::new(py, &[sigint_py_const]),
       
   140             None,
       
   141         )?;
       
   142     }
       
   143     Ok(res)
       
   144 }