author | Pierre-Yves David <pierre-yves.david@octobus.net> |
Thu, 02 Jan 2025 14:50:06 +0100 | |
changeset 52592 | 87ceb51d124c |
parent 52533 | 6b694bdf752a |
permissions | -rw-r--r-- |
52411
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::*; |
52528
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
diff
changeset
|
14 |
use pyo3::{pyclass::boolean_struct::False, PyClass}; |
52411
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 |
|
52414
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
20 |
use hg::revlog::index::Index as CoreIndex; |
52411
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 |
|
52528
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
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:
52527
diff
changeset
|
24 |
/// |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
diff
changeset
|
25 |
/// # Safety |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
diff
changeset
|
26 |
/// |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
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:
52527
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:
52527
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:
52527
diff
changeset
|
30 |
|
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
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:
52527
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:
52527
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:
52527
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:
52527
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:
52527
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:
52527
diff
changeset
|
37 |
{ |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
diff
changeset
|
38 |
} |
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
diff
changeset
|
39 |
|
52411
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> |
52528
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
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:
52527
diff
changeset
|
53 |
_with_gil: &T, |
52411
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
54 |
) -> cpython::Python<'py> { |
52528
1dd673c1ab3b
rust-pyo3: getting rust-cpython GIL handle from various PyO3 objects
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52527
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:
52527
diff
changeset
|
56 |
// as the incoming object. |
52411
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 |
|
52527
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
188 |
pub(crate) fn proxy_index_py_leak<'py>( |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
189 |
index_proxy: &Bound<'py, PyAny>, |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
190 |
) -> PyResult<(cpython::Python<'py>, cpython::UnsafePyLeaked<PySharedIndex>)> { |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
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:
52414
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:
52414
diff
changeset
|
193 |
Ok((py, py_leaked)) |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
194 |
} |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
195 |
|
52414
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
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:
52411
diff
changeset
|
197 |
/// [`CoreIndex`] reference. |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
198 |
/// |
52527
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
199 |
/// # Safety |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
200 |
/// |
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
201 |
/// The invariants to maintain are those of the underlying |
52414
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
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:
52411
diff
changeset
|
203 |
/// reference. |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
204 |
pub(crate) unsafe fn proxy_index_extract<'py>( |
52411
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
205 |
index_proxy: &Bound<'py, PyAny>, |
52414
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
206 |
) -> PyResult<&'py CoreIndex> { |
52527
64a618048ba8
rust-pyo3: intermediate ProxyIndex extraction
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52414
diff
changeset
|
207 |
let (py, py_leaked) = proxy_index_py_leak(index_proxy)?; |
52414
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
208 |
let py_shared = &*unsafe { |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
209 |
py_leaked |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
210 |
.try_borrow(py) |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
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:
52411
diff
changeset
|
212 |
}; |
233707101dae
rust-pyo3: simplified API to get core Index references
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52411
diff
changeset
|
213 |
Ok(py_shared.inner) |
52411
c2480ac4c5e2
rust-pyo3: retrieving the InnerRevlog of hg-cpython
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
diff
changeset
|
214 |
} |
52529
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
215 |
|
52530
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
216 |
/// Generic borrow of [`cpython::UnsafePyLeaked`], with proper mapping. |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
217 |
/// |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
218 |
/// # Safety |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
219 |
/// |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
220 |
/// The invariants to maintain are those of the underlying |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
221 |
/// [`UnsafePyLeaked::try_borrow`]: the caller must not leak the inner |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
222 |
/// static reference. It is possible, depending on `T` that such a leak cannot |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
223 |
/// occur in practice. We may later on define a marker trait for this, |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
224 |
/// which will allow us to make declare this function to be safe. |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
225 |
pub(crate) unsafe fn py_leaked_borrow<'a, 'py: 'a, T>( |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
226 |
py: &impl WithGIL<'py>, |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
227 |
leaked: &'a cpython::UnsafePyLeaked<T>, |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
228 |
) -> PyResult<cpython::PyLeakedRef<'a, T>> { |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
229 |
let py = cpython_handle(py); |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
230 |
leaked.try_borrow(py).map_err(|e| from_cpython_pyerr(py, e)) |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
231 |
} |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
232 |
|
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
233 |
/// Mutable variant of [`py_leaked_borrow`] |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
234 |
/// |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
235 |
/// # Safety |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
236 |
/// |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
237 |
/// See [`py_leaked_borrow`] |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
238 |
pub(crate) unsafe fn py_leaked_borrow_mut<'a, 'py: 'a, T>( |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
239 |
py: &impl WithGIL<'py>, |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
240 |
leaked: &'a mut cpython::UnsafePyLeaked<T>, |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
241 |
) -> PyResult<cpython::PyLeakedRefMut<'a, T>> { |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
242 |
let py = cpython_handle(py); |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
243 |
leaked |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
244 |
.try_borrow_mut(py) |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
245 |
.map_err(|e| from_cpython_pyerr(py, e)) |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
246 |
} |
736551565871
rust-pyo3: generic borrows of UnsafePyLeaked with error treatment
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52529
diff
changeset
|
247 |
|
52529
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
248 |
/// 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:
52528
diff
changeset
|
249 |
/// |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
250 |
/// 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:
52528
diff
changeset
|
251 |
/// 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:
52528
diff
changeset
|
252 |
/// 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:
52528
diff
changeset
|
253 |
/// |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
254 |
/// ``` |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
255 |
/// unsafe fn map_or_err(&self, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
256 |
/// py: Python, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
257 |
/// f: impl FnOnce(T) -> Result(U, E), |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
258 |
/// convert_err: impl FnOnce(E) -> PyErr) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
259 |
/// ``` |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
260 |
/// |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
261 |
/// 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:
52528
diff
changeset
|
262 |
/// 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:
52528
diff
changeset
|
263 |
/// subsequent unwrapping that this function performs. |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
264 |
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:
52528
diff
changeset
|
265 |
py: cpython::Python, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
266 |
leaked: cpython::UnsafePyLeaked<Result<T, E>>, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
267 |
convert_err: impl FnOnce(E) -> PyErr, |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
268 |
) -> PyResult<cpython::UnsafePyLeaked<T>> { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
269 |
// 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:
52528
diff
changeset
|
270 |
if let Err(e) = *unsafe { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
271 |
leaked |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
272 |
.try_borrow(py) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
273 |
.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:
52528
diff
changeset
|
274 |
} { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
275 |
return Err(convert_err(e)); |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
276 |
} |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
277 |
// 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:
52528
diff
changeset
|
278 |
Ok(unsafe { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
279 |
leaked.map(py, |res| { |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
280 |
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:
52528
diff
changeset
|
281 |
}) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
282 |
}) |
bd65cb043aa5
rust-pyo3: error propagation for UnsafePyLeaked wrapping a result
Georges Racinet <georges.racinet@cloudcrane.io>
parents:
52528
diff
changeset
|
283 |
} |