Mercurial > public > mercurial-scm > hg
annotate rust/hg-pyo3/src/utils.rs @ 53042:cdd7bf612c7b stable tip
bundle-spec: properly format boolean parameter (issue6960)
This was breaking automatic clone bundle generation. This changeset fixes it and
add a test to catch it in the future.
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 11 Mar 2025 02:29:42 +0100 |
parents | 69d40a9778fe |
children |
rev | line source |
---|---|
52822
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
1 use hg::errors::HgError; |
52836
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
2 use hg::revlog::index::Index as CoreIndex; |
52822
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
3 use hg::revlog::inner_revlog::RevisionBuffer; |
52780
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
4 use pyo3::buffer::{Element, PyBuffer}; |
52977
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
5 use pyo3::exceptions::{ |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
6 PyIOError, PyKeyboardInterrupt, PyRuntimeError, PyValueError, |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
7 }; |
52822
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
8 use pyo3::types::{PyBytes, PyDict}; |
52977
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
9 use pyo3::{intern, prelude::*}; |
52836
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
10 use pyo3_sharedref::SharedByPyObject; |
52830
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
11 use stable_deref_trait::StableDeref; |
52822
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
12 |
52977
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
13 use crate::exceptions::FallbackError; |
52836
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
14 use crate::revlog::{InnerRevlog, PySharedIndex}; |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
15 |
52407
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
16 /// Create the module, with `__package__` given from parent |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
17 /// |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
18 /// According to PyO3 documentation, which links to |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
19 /// <https://github.com/PyO3/pyo3/issues/1517>, the same convoluted |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
20 /// write to sys.modules has to be made as with the `cpython` crate. |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
21 pub(crate) fn new_submodule<'py>( |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
22 py: Python<'py>, |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
23 package_name: &str, |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
24 name: &str, |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
25 ) -> PyResult<Bound<'py, PyModule>> { |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
26 let dotted_name = &format!("{}.{}", package_name, name); |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
27 let m = PyModule::new(py, name)?; |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
28 m.add("__package__", package_name)?; |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
29 |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
30 let sys = PyModule::import(py, "sys")?; |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
31 // according to the doc, we could make a static PyString out of |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
32 // "modules" with the `intern!` macro, but this is used only at |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
33 // registration so it may not be worth the effort. |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
34 let sys_modules: Bound<'_, PyDict> = sys.getattr("modules")?.extract()?; |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
35 sys_modules.set_item(dotted_name, &m)?; |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
36 // Example C code (see pyexpat.c and import.c) will "give away the |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
37 // reference", but we won't because it will be consumed once the |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
38 // Rust PyObject is dropped. |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
39 Ok(m) |
c5128c541021
rust-pyo3: facility for submodule registration, using it for dagop
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
40 } |
52780
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
41 |
52836
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
42 /// Retrieve the shared index wrapper (which contains the core index) |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
43 /// from the Python index proxy. |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
44 pub fn py_rust_index_to_graph( |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
45 index_proxy: &Bound<'_, PyAny>, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
46 ) -> PyResult<SharedByPyObject<PySharedIndex>> { |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
47 let py_irl = index_proxy.getattr("inner")?; |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
48 let py_irl_ref = py_irl.downcast::<InnerRevlog>()?.borrow(); |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
49 let shareable_irl = &py_irl_ref.irl; |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
50 |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
51 // Safety: the owner is the actual one and we do not leak any |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
52 // internal reference. |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
53 let index = |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
54 unsafe { shareable_irl.share_map(&py_irl, |irl| (&irl.index).into()) }; |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
55 Ok(index) |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
56 } |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
57 |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
58 /// Error propagation for an [`SharedByPyObject`] wrapping a [`Result`] |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
59 /// |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
60 /// It would be nice for [`SharedByPyObject`] to provide this directly as |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
61 /// a variant of the `map` method with a signature such as: |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
62 /// |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
63 /// ``` |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
64 /// unsafe fn map_or_err(&self, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
65 /// py: Python, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
66 /// f: impl FnOnce(T) -> Result(U, E), |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
67 /// convert_err: impl FnOnce(E) -> PyErr) |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
68 /// ``` |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
69 /// |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
70 /// This would spare users of the `pyo3` crate the additional `unsafe` deref |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
71 /// to inspect the error and return it outside `SharedByPyObject`, and the |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
72 /// subsequent unwrapping that this function performs. |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
73 pub(crate) fn py_shared_or_map_err<T, E: std::fmt::Debug + Copy>( |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
74 py: Python, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
75 leaked: SharedByPyObject<Result<T, E>>, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
76 convert_err: impl FnOnce(E) -> PyErr, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
77 ) -> PyResult<SharedByPyObject<T>> { |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
78 // Safety: we don't leak the "faked" reference out of `SharedByPyObject` |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
79 if let Err(e) = *unsafe { leaked.try_borrow(py)? } { |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
80 return Err(convert_err(e)); |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
81 } |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
82 // Safety: we don't leak the "faked" reference out of `SharedByPyObject` |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
83 Ok(unsafe { |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
84 leaked.map(py, |res| { |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
85 res.expect("Error case should have already be treated") |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
86 }) |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
87 }) |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
88 } |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
89 |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
90 /// Full extraction of the proxy index object as received in PyO3 to a |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
91 /// [`CoreIndex`] reference. |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
92 /// |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
93 /// # Safety |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
94 /// |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
95 /// The invariants to maintain are those of the underlying |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
96 /// [`SharedByPyObject::try_borrow`]: the caller must not leak the inner |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
97 /// reference. |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
98 pub(crate) unsafe fn proxy_index_extract<'py>( |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
99 index_proxy: &Bound<'py, PyAny>, |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
100 ) -> PyResult<&'py CoreIndex> { |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
101 let py_shared = py_rust_index_to_graph(index_proxy)?; |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
102 let py_shared = &*unsafe { py_shared.try_borrow(index_proxy.py())? }; |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
103 Ok(unsafe { py_shared.static_inner() }) |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
104 } |
9749a97d3cfb
rust-pyo3: introduce utils to get the pyo3-wrapped index from Python
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52830
diff
changeset
|
105 |
52780
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
106 /// Type shortcut for the kind of bytes slice trait objects that are used in |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
107 /// particular for mmap data |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
108 type BoxedBytesSlice = |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
109 Box<dyn std::ops::Deref<Target = [u8]> + Send + Sync + 'static>; |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
110 |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
111 /// Take a Python object backed by a Python buffer, and return the underlying |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
112 /// [`PyBuffer`] along with the Rust slice into said buffer. |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
113 /// |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
114 /// The caller needs to make sure that the Python buffer is not freed before |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
115 /// the slice, otherwise we'd get a dangling pointer once the incoming |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
116 /// object is freed from Python side. This can be achieved by storing it a |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
117 /// Python object. |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
118 /// |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
119 /// The typical use case is to extract mmap data to make it useable in the |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
120 /// constructs from the `hg` crate. |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
121 /// |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
122 /// # Safety |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
123 /// |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
124 /// The caller must make sure that the incoming Python object is kept around |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
125 /// for at least as long as the returned [`BoxedBytesSlice`]. |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
126 // TODO in PyO3, we already get a reference with two lifetimes, and we |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
127 // could even take a `Borrowed<'a, 'py, T>`. |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
128 // So perhaps we could tie everything together with a lifetime so that is |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
129 // is, after all, safe, and this could be called something like `share_buffer`. |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
130 #[deny(unsafe_op_in_unsafe_fn)] |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
131 pub unsafe fn take_buffer_with_slice( |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
132 data: &Bound<'_, PyAny>, |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
133 ) -> PyResult<(PyBuffer<u8>, BoxedBytesSlice)> { |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
134 let buf = PyBuffer::<u8>::get(data)?; |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
135 let len = buf.item_count(); |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
136 |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
137 // Build a slice from the buffer data |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
138 let cbuf = buf.buf_ptr(); |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
139 let bytes = if std::mem::size_of::<u8>() == buf.item_size() |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
140 && buf.is_c_contiguous() |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
141 && u8::is_compatible_format(buf.format()) |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
142 && buf.dimensions() == 1 |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
143 && buf.readonly() |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
144 { |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
145 unsafe { std::slice::from_raw_parts(cbuf as *const u8, len) } |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
146 } else { |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
147 return Err(PyValueError::new_err( |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
148 "buffer has an invalid memory representation", |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
149 )); |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
150 }; |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
151 |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
152 Ok((buf, Box::new(bytes))) |
42b219a1404a
rust-pyo3-revlog: InnerRevlog definition and constructor
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52407
diff
changeset
|
153 } |
52822
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
154 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
155 /// Takes an initialization function `init` which writes bytes to a |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
156 /// Python-backed buffer, to save on a (potentially large) memory allocation |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
157 /// and copy. If `init` fails to write the full expected length `len`, an error |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
158 /// is raised. |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
159 pub fn with_pybytes_buffer<F>( |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
160 py: Python, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
161 len: usize, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
162 init: F, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
163 ) -> Result<Py<PyBytes>, hg::revlog::RevlogError> |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
164 where |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
165 F: FnOnce( |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
166 &mut dyn RevisionBuffer<Target = Py<PyBytes>>, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
167 ) -> Result<(), hg::revlog::RevlogError>, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
168 { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
169 // Largely inspired by code in PyO3 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
170 // https://pyo3.rs/main/doc/pyo3/types/struct.pybytes#method.new_bound_with |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
171 unsafe { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
172 let pyptr = pyo3::ffi::PyBytes_FromStringAndSize( |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
173 std::ptr::null(), |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
174 len as pyo3::ffi::Py_ssize_t, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
175 ); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
176 let pybytes = Bound::from_owned_ptr_or_err(py, pyptr) |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
177 .map_err(|e| HgError::abort_simple(e.to_string()))? |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
178 .downcast_into_unchecked(); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
179 let buffer: *mut u8 = pyo3::ffi::PyBytes_AsString(pyptr).cast(); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
180 debug_assert!(!buffer.is_null()); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
181 let mut rev_buf = PyRevisionBuffer::new(pybytes.unbind(), buffer, len); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
182 // Initialise the bytestring in init |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
183 // If init returns an Err, the buffer is deallocated by `pybytes` |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
184 init(&mut rev_buf).map(|_| rev_buf.finish()) |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
185 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
186 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
187 |
52830
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
188 /// Safe abstraction over a `PyBytes` together with the `&[u8]` slice |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
189 /// that borrows it. Implements `Deref<Target = [u8]>`. |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
190 /// |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
191 /// Calling `PyBytes::data` requires a GIL marker but we want to access the |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
192 /// data in a thread that (ideally) does not need to acquire the GIL. |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
193 /// This type allows separating the call an the use. |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
194 /// |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
195 /// It also enables using a (wrapped) `PyBytes` in GIL-unaware generic code. |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
196 pub struct PyBytesDeref { |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
197 #[allow(unused)] |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
198 keep_alive: Py<PyBytes>, |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
199 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
200 /// Borrows the buffer inside `self.keep_alive`, |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
201 /// but the borrow-checker cannot express self-referential structs. |
52852
6b3b69b32a41
rust-pyo3: making PyBytesDeref Sync
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52841
diff
changeset
|
202 data: &'static [u8], |
52830
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
203 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
204 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
205 impl PyBytesDeref { |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
206 pub fn new(py: Python, bytes: Py<PyBytes>) -> Self { |
52852
6b3b69b32a41
rust-pyo3: making PyBytesDeref Sync
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52841
diff
changeset
|
207 let as_raw: *const [u8] = bytes.as_bytes(py); |
52830
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
208 Self { |
52852
6b3b69b32a41
rust-pyo3: making PyBytesDeref Sync
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52841
diff
changeset
|
209 // Safety: the raw pointer is valid as long as the PyBytes is still |
6b3b69b32a41
rust-pyo3: making PyBytesDeref Sync
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52841
diff
changeset
|
210 // alive, and the objecs owns it. |
6b3b69b32a41
rust-pyo3: making PyBytesDeref Sync
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52841
diff
changeset
|
211 data: unsafe { &*as_raw }, |
52830
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
212 keep_alive: bytes, |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
213 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
214 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
215 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
216 #[allow(unused)] |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
217 pub fn unwrap(self) -> Py<PyBytes> { |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
218 self.keep_alive |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
219 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
220 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
221 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
222 impl std::ops::Deref for PyBytesDeref { |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
223 type Target = [u8]; |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
224 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
225 fn deref(&self) -> &[u8] { |
52852
6b3b69b32a41
rust-pyo3: making PyBytesDeref Sync
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52841
diff
changeset
|
226 self.data |
52830
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
227 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
228 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
229 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
230 unsafe impl StableDeref for PyBytesDeref {} |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
231 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
232 fn require_send<T: Send>() {} |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
233 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
234 #[allow(unused)] |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
235 fn static_assert_pybytes_is_send() { |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
236 #[allow(clippy::no_effect)] |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
237 require_send::<Py<PyBytes>>; |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
238 } |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
239 |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
240 // Safety: `[Py<PyBytes>]` is Send. Raw pointers are not by default, |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
241 // but here sending one to another thread is fine since we ensure it stays |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
242 // valid. |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
243 unsafe impl Send for PyBytesDeref {} |
dd3a2948804f
rust-pyo3: add `PyBytesDeref` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52822
diff
changeset
|
244 |
52822
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
245 /// Wrapper around a Python-provided buffer into which the revision contents |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
246 /// will be written. Done for speed in order to save a large allocation + copy. |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
247 struct PyRevisionBuffer { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
248 py_bytes: Py<PyBytes>, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
249 _buf: *mut u8, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
250 len: usize, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
251 current_buf: *mut u8, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
252 current_len: usize, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
253 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
254 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
255 impl PyRevisionBuffer { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
256 /// # Safety |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
257 /// |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
258 /// `buf` should be the start of the allocated bytes of `bytes`, and `len` |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
259 /// exactly the length of said allocated bytes. |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
260 #[inline] |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
261 unsafe fn new(bytes: Py<PyBytes>, buf: *mut u8, len: usize) -> Self { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
262 Self { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
263 py_bytes: bytes, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
264 _buf: buf, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
265 len, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
266 current_len: 0, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
267 current_buf: buf, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
268 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
269 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
270 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
271 /// Number of bytes that have been copied to. Will be different to the |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
272 /// total allocated length of the buffer unless the revision is done being |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
273 /// written. |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
274 #[inline] |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
275 fn current_len(&self) -> usize { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
276 self.current_len |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
277 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
278 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
279 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
280 impl RevisionBuffer for PyRevisionBuffer { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
281 type Target = Py<PyBytes>; |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
282 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
283 #[inline] |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
284 fn extend_from_slice(&mut self, slice: &[u8]) { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
285 assert!(self.current_len + slice.len() <= self.len); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
286 unsafe { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
287 // We cannot use `copy_from_nonoverlapping` since it's *possible* |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
288 // to create a slice from the same Python memory region using |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
289 // [`PyBytesDeref`]. Probable that LLVM has an optimization anyway? |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
290 self.current_buf.copy_from(slice.as_ptr(), slice.len()); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
291 self.current_buf = self.current_buf.add(slice.len()); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
292 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
293 self.current_len += slice.len() |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
294 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
295 |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
296 #[inline] |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
297 fn finish(self) -> Self::Target { |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
298 // catch unzeroed bytes before it becomes undefined behavior |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
299 assert_eq!( |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
300 self.current_len(), |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
301 self.len, |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
302 "not enough bytes read for revision" |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
303 ); |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
304 self.py_bytes |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
305 } |
4f41a8acf350
rust-pyo3: add a `with_pybytes_buffer` util
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52780
diff
changeset
|
306 } |
52977
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
307 |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
308 /// Extension trait to help with generic error conversions from hg-core to |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
309 /// Python. |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
310 pub(crate) trait HgPyErrExt<T> { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
311 fn into_pyerr(self, py: Python) -> PyResult<T>; |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
312 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
313 |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
314 impl<T, E> HgPyErrExt<T> for Result<T, E> |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
315 where |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
316 HgError: From<E>, |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
317 { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
318 fn into_pyerr(self, py: Python) -> PyResult<T> { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
319 self.map_err(|e| match e.into() { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
320 err @ HgError::IoError { .. } => { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
321 PyIOError::new_err(err.to_string()) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
322 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
323 HgError::UnsupportedFeature(e) => { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
324 FallbackError::new_err(e.to_string()) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
325 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
326 HgError::RaceDetected(_) => { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
327 unreachable!("must not surface to the user") |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
328 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
329 HgError::Path(path_error) => { |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
330 let msg = PyBytes::new(py, path_error.to_string().as_bytes()); |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
331 let cls = py |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
332 .import(intern!(py, "mercurial.error")) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
333 .and_then(|m| m.getattr(intern!(py, "InputError"))) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
334 .expect("failed to import InputError"); |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
335 PyErr::from_value( |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
336 cls.call1((msg,)) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
337 .expect("initializing an InputError failed"), |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
338 ) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
339 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
340 HgError::InterruptReceived => PyKeyboardInterrupt::new_err(()), |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
341 e => PyRuntimeError::new_err(e.to_string()), |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
342 }) |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
343 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
344 } |
0c7ac026ed63
pyo3: add a generic error conversion extension trait
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52976
diff
changeset
|
345 |
52978
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
346 /// Wrap a call to `func` so that Python's `SIGINT` handler is first stored, |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
347 /// then restored after the call to `func` and finally raised if |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
348 /// `func` returns a [`HgError::InterruptReceived`]. |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
349 /// |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
350 /// We cannot use [`Python::check_signals`] because it only works from the main |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
351 /// thread of the main interpreter. To that end, long-running Rust functions |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
352 /// need to cooperate by listening to their own `SIGINT` signal and return |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
353 /// the appropriate error on catching that signal: this is especially helpful |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
354 /// in multithreaded operations. |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
355 pub fn with_sigint_wrapper<R>( |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
356 py: Python, |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
357 func: impl Fn() -> Result<R, HgError>, |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
358 ) -> PyResult<Result<R, HgError>> { |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
359 let signal_py_mod = py.import(intern!(py, "signal"))?; |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
360 let sigint_py_const = signal_py_mod.getattr(intern!(py, "SIGINT"))?; |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
361 let old_handler = signal_py_mod |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
362 .call_method1(intern!(py, "getsignal"), (sigint_py_const.clone(),))?; |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
363 let res = func(); |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
364 // Reset the old signal handler in Python because we may have changed it |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
365 signal_py_mod.call_method1( |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
366 intern!(py, "signal"), |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
367 (sigint_py_const.clone(), old_handler), |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
368 )?; |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
369 if let Err(HgError::InterruptReceived) = res { |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
370 // Trigger the signal in Python |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
371 signal_py_mod |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
372 .call_method1(intern!(py, "raise_signal"), (sigint_py_const,))?; |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
373 } |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
374 Ok(res) |
69d40a9778fe
pyo3: add a util to handle SIGINT from a long-running Rust function
Rapha?l Gom?s <rgomes@octobus.net>
parents:
52977
diff
changeset
|
375 } |