Mercurial > public > mercurial-scm > hg-stable
annotate rust/hg-pyo3/src/convert_cpython.rs @ 52556:bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
This `py_leaked_or_map_err` is the PyO3 version of the function
of the same name in `hg-cpython/src/ancestors.rs`.
author | Georges Racinet <georges.racinet@cloudcrane.io> |
---|---|
date | Sat, 07 Dec 2024 18:18:09 +0100 |
parents | 1dd673c1ab3b |
children | 736551565871 |
rev | line source |
---|---|
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
1 //! This module takes care of all conversions involving `rusthg` (hg-cpython) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
2 //! objects in the PyO3 call context. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
3 //! |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
4 //! For source code clarity, we only import (`use`) [`cpython`] traits and not |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
5 //! any of its data objects. We are instead using full qualifiers, such as |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
6 //! `cpython::PyObject`, and believe that the added heaviness is an acceptatble |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
7 //! price to pay to avoid confusion. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
8 //! |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
9 //! Also it, is customary in [`cpython`] to label the GIL lifetime as `'p`, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
10 //! whereas it is `'py` in PyO3 context. We keep both these conventions in |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
11 //! the arguments side of function signatures when they are not simply elided. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
12 use pyo3::exceptions::PyTypeError; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
13 use pyo3::prelude::*; |
52555
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
14 use pyo3::{pyclass::boolean_struct::False, PyClass}; |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
15 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
16 use cpython::ObjectProtocol; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
17 use cpython::PythonObject; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
18 use lazy_static::lazy_static; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
19 |
52445
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
20 use hg::revlog::index::Index as CoreIndex; |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
21 use rusthg::revlog::{InnerRevlog, PySharedIndex}; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
22 |
52555
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
23 /// Marker trait for PyO3 objects with a lifetime representing the acquired GIL |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
24 /// |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
25 /// # Safety |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
26 /// |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
27 /// This trait must not be implemented for objects with lifetimes that |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
28 /// do not imply in PyO3 that the GIL is acquired during the whole lifetime. |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
29 pub unsafe trait WithGIL<'py> {} |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
30 |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
31 // Safety: the lifetime on these PyO3 objects all represent the acquired GIL |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
32 unsafe impl<'py> WithGIL<'py> for Python<'py> {} |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
33 unsafe impl<'py, T> WithGIL<'py> for Bound<'py, T> {} |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
34 unsafe impl<'py, T: PyClass> WithGIL<'py> for PyRef<'py, T> {} |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
35 unsafe impl<'py, T: PyClass<Frozen = False>> WithGIL<'py> |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
36 for PyRefMut<'py, T> |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
37 { |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
38 } |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
39 |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
40 /// Force cpython's GIL handle with the appropriate lifetime |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
41 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
42 /// In `pyo3`, the fact that we have the GIL is expressed by the lifetime of |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
43 /// the incoming [`Bound`] smart pointer. We therefore simply instantiate |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
44 /// the `cpython` handle and coerce its lifetime by the function signature. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
45 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
46 /// Reacquiring the GIL is also a possible alternative, as the CPython |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
47 /// documentation explicitely states that "recursive calls are allowed" |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
48 /// (we interpret that as saying that acquiring the GIL within a thread that |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
49 /// already has it works) *as long as it is properly released* |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
50 /// reference: |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
51 /// <https://docs.python.org/3.8/c-api/init.html#c.PyGILState_Ensure> |
52555
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
52 pub(crate) fn cpython_handle<'py, T: WithGIL<'py>>( |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
53 _with_gil: &T, |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
54 ) -> cpython::Python<'py> { |
52555
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
55 // safety: this is safe because the returned object has the same lifetime |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52554
diff
changeset
|
56 // as the incoming object. |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
57 unsafe { cpython::Python::assume_gil_acquired() } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
58 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
59 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
60 /// Force PyO3 GIL handle from cpython's. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
61 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
62 /// Very similar to [`cpython_handle`] |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
63 pub fn pyo3_handle(_py: cpython::Python<'_>) -> Python<'_> { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
64 // safety: this is safe because the returned object has the same lifetime |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
65 // as the incoming object. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
66 unsafe { Python::assume_gil_acquired() } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
67 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
68 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
69 /// Convert a PyO3 [`PyObject`] into a [`cpython::PyObject`] |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
70 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
71 /// During this process, the reference count is increased, then decreased. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
72 /// This means that the GIL (symbolized by the lifetime on the `obj` |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
73 /// argument) is needed. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
74 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
75 /// We could make something perhaps more handy by simply stealing the |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
76 /// pointer, forgetting the incoming and then implement `From` with "newtype". |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
77 /// It would be worth the effort for a generic cpython-to-pyo3 crate, perhaps |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
78 /// not for the current endeavour. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
79 pub(crate) fn to_cpython_py_object<'py>( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
80 obj: &Bound<'py, PyAny>, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
81 ) -> (cpython::Python<'py>, cpython::PyObject) { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
82 let py = cpython_handle(obj); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
83 // public alias of the private cpython::fii::PyObject (!) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
84 let raw = obj.as_ptr() as *mut python3_sys::PyObject; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
85 // both pyo3 and rust-cpython will decrement the refcount on drop. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
86 // If we use from_owned_ptr, that's a segfault. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
87 (py, unsafe { cpython::PyObject::from_borrowed_ptr(py, raw) }) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
88 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
89 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
90 /// Convert a [`cpython::PyObject`] into a PyO3 [`PyObject`] |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
91 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
92 /// During this process, the reference count is increased, then decreased. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
93 /// This means that the GIL (symbolized by the PyO3 [`Python`] handle is |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
94 /// needed. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
95 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
96 /// We could make something perhaps more handy by simply stealing the |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
97 /// pointer, forgetting the incoming and then implement `From` with "newtype". |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
98 /// It would be worth the effort for a generic cpython-to-pyo3 crate, perhaps |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
99 /// not for the current endeavour. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
100 pub(crate) fn from_cpython_py_object( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
101 py: Python<'_>, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
102 obj: cpython::PyObject, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
103 ) -> PyObject { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
104 let raw = obj.as_ptr() as *mut pyo3::ffi::PyObject; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
105 unsafe { Py::from_borrowed_ptr(py, raw) } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
106 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
107 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
108 /// Convert [`cpython::PyErr`] into [`pyo3::PyErr`] |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
109 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
110 /// The exception class remains the same as the original exception, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
111 /// hence if it is also defined in another dylib based on `cpython` crate, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
112 /// it will need to be converted to be downcasted in this crate. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
113 pub(crate) fn from_cpython_pyerr( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
114 py: cpython::Python<'_>, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
115 mut e: cpython::PyErr, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
116 ) -> PyErr { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
117 let pyo3_py = pyo3_handle(py); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
118 let cpython_exc_obj = e.instance(py); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
119 let pyo3_exc_obj = from_cpython_py_object(pyo3_py, cpython_exc_obj); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
120 PyErr::from_value(pyo3_exc_obj.into_bound(pyo3_py)) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
121 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
122 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
123 /// Retrieve the PyType for objects from the `mercurial.rustext` crate. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
124 fn retrieve_cpython_py_type( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
125 submodule_name: &str, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
126 type_name: &str, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
127 ) -> cpython::PyResult<cpython::PyType> { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
128 let guard = cpython::Python::acquire_gil(); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
129 let py = guard.python(); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
130 let module = py.import(&format!("mercurial.rustext.{submodule_name}"))?; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
131 module.get(py, type_name)?.extract::<cpython::PyType>(py) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
132 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
133 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
134 lazy_static! { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
135 static ref INNER_REVLOG_PY_TYPE: cpython::PyType = { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
136 retrieve_cpython_py_type("revlog", "InnerRevlog") |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
137 .expect("Could not import InnerRevlog in Python") |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
138 }; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
139 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
140 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
141 /// Downcast [`InnerRevlog`], with the appropriate Python type checking. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
142 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
143 /// The PyType object representing the `InnerRevlog` Python class is not the |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
144 /// the same in this dylib as it is in the `mercurial.rustext` module. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
145 /// This is because the code created with the [`cpython::py_class!`] |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
146 /// macro is itself duplicated in both dylibs. In the case of this crate, this |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
147 /// happens by linking to the [`rusthg`] crate and provides the `InnerRevlog` |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
148 /// that is visible from this crate. The `InnerRevlog::get_type` associated |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
149 /// function turns out to return a `static mut` (look for `TYPE_OBJECT` in |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
150 /// `py_class_impl3.rs`), which obviously is different in both dylibs. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
151 /// |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
152 /// The consequence of that is that downcasting an `InnerRevlog` originally |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
153 /// from the `mecurial.rustext` module to our `InnerRevlog` cannot be done with |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
154 /// the usual `extract::<InnerRevlog>(py)`, as it would perform the type |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
155 /// checking with the `PyType` that is embedded in `mercurial.pyo3_rustext`. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
156 /// We must check the `PyType` that is within `mercurial.rustext` instead. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
157 /// This is what this function does. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
158 fn extract_inner_revlog( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
159 py: cpython::Python, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
160 inner_revlog: cpython::PyObject, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
161 ) -> PyResult<InnerRevlog> { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
162 if !(*INNER_REVLOG_PY_TYPE).is_instance(py, &inner_revlog) { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
163 return Err(PyTypeError::new_err("Not an InnerRevlog instance")); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
164 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
165 // Safety: this is safe because we checked the PyType already, with the |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
166 // value embedded in `mercurial.rustext`. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
167 Ok(unsafe { InnerRevlog::unchecked_downcast_from(inner_revlog) }) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
168 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
169 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
170 /// This is similar to [`rusthg.py_rust_index_to_graph`], with difference in |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
171 /// how we retrieve the [`InnerRevlog`]. |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
172 pub fn py_rust_index_to_graph( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
173 py: cpython::Python, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
174 index_proxy: cpython::PyObject, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
175 ) -> PyResult<cpython::UnsafePyLeaked<PySharedIndex>> { |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
176 let inner_revlog = extract_inner_revlog( |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
177 py, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
178 index_proxy |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
179 .getattr(py, "inner") |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
180 .map_err(|e| from_cpython_pyerr(py, e))?, |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
181 )?; |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
182 |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
183 let leaked = inner_revlog.pub_inner(py).leak_immutable(); |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
184 // Safety: we don't leak the "faked" reference out of the `UnsafePyLeaked` |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
185 Ok(unsafe { leaked.map(py, |idx| PySharedIndex { inner: &idx.index }) }) |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
186 } |
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
187 |
52554
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
188 pub(crate) fn proxy_index_py_leak<'py>( |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
189 index_proxy: &Bound<'py, PyAny>, |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
190 ) -> PyResult<(cpython::Python<'py>, cpython::UnsafePyLeaked<PySharedIndex>)> { |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
191 let (py, idx_proxy) = to_cpython_py_object(index_proxy); |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
192 let py_leaked = py_rust_index_to_graph(py, idx_proxy)?; |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
193 Ok((py, py_leaked)) |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
194 } |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
195 |
52445
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
196 /// Full extraction of the proxy index object as received in PyO3 to a |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
197 /// [`CoreIndex`] reference. |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
198 /// |
52554
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
199 /// # Safety |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
200 /// |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
201 /// The invariants to maintain are those of the underlying |
52445
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
202 /// [`UnsafePyLeaked::try_borrow`]: the caller must not leak the inner |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
203 /// reference. |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
204 pub(crate) unsafe fn proxy_index_extract<'py>( |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
205 index_proxy: &Bound<'py, PyAny>, |
52445
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
206 ) -> PyResult<&'py CoreIndex> { |
52554
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52445
diff
changeset
|
207 let (py, py_leaked) = proxy_index_py_leak(index_proxy)?; |
52445
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
208 let py_shared = &*unsafe { |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
209 py_leaked |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
210 .try_borrow(py) |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
211 .map_err(|e| from_cpython_pyerr(py, e))? |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
212 }; |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52442
diff
changeset
|
213 Ok(py_shared.inner) |
52442
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
214 } |
52556
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
215 |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
216 /// Error propagation for an [`UnsafePyLeaked`] wrapping a [`Result`] |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
217 /// |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
218 /// TODO (will consider when implementing UnsafePyLeaked in PyO3): |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
219 /// It would be nice for UnsafePyLeaked to provide this directly as a variant |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
220 /// of the `map` method with a signature such as: |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
221 /// |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
222 /// ``` |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
223 /// unsafe fn map_or_err(&self, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
224 /// py: Python, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
225 /// f: impl FnOnce(T) -> Result(U, E), |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
226 /// convert_err: impl FnOnce(E) -> PyErr) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
227 /// ``` |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
228 /// |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
229 /// This would spare users of the `cpython` crate the additional `unsafe` deref |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
230 /// to inspect the error and return it outside `UnsafePyLeaked`, and the |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
231 /// subsequent unwrapping that this function performs. |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
232 #[allow(dead_code)] |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
233 pub(crate) fn py_leaked_or_map_err<T, E: std::fmt::Debug + Copy>( |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
234 py: cpython::Python, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
235 leaked: cpython::UnsafePyLeaked<Result<T, E>>, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
236 convert_err: impl FnOnce(E) -> PyErr, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
237 ) -> PyResult<cpython::UnsafePyLeaked<T>> { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
238 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
239 if let Err(e) = *unsafe { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
240 leaked |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
241 .try_borrow(py) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
242 .map_err(|e| from_cpython_pyerr(py, e))? |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
243 } { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
244 return Err(convert_err(e)); |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
245 } |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
246 // Safety: we don't leak the "faked" reference out of `UnsafePyLeaked` |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
247 Ok(unsafe { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
248 leaked.map(py, |res| { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
249 res.expect("Error case should have already be treated") |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
250 }) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
251 }) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52555
diff
changeset
|
252 } |