File: test_pyself.rs

package info (click to toggle)
rust-pyo3 0.28.2-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,768 kB
  • sloc: javascript: 59; makefile: 58; python: 39; sh: 1
file content (125 lines) | stat: -rw-r--r-- 3,122 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#![cfg(feature = "macros")]

//! Test slf: PyRef/PyMutRef<Self>(especially, slf.into::<Py>) works
use pyo3::prelude::*;
use pyo3::types::{PyBytes, PyString};
use std::collections::HashMap;

mod test_utils;

/// Assumes it's a file reader or so.
/// Inspired by https://github.com/jothan/cordoba, thanks.
#[pyclass(skip_from_py_object)]
#[derive(Clone, Debug)]
struct Reader {
    inner: HashMap<u8, String>,
}

#[pymethods]
impl Reader {
    fn clone_ref<'a, 'py>(slf: &'a Bound<'py, Self>) -> &'a Bound<'py, Self> {
        slf
    }
    fn clone_ref_with_py<'a, 'py>(
        slf: &'a Bound<'py, Self>,
        _py: Python<'py>,
    ) -> &'a Bound<'py, Self> {
        slf
    }
    fn get_iter(slf: &Bound<'_, Self>, keys: Py<PyBytes>) -> Iter {
        Iter {
            reader: slf.clone().unbind(),
            keys,
            idx: 0,
        }
    }
    fn get_iter_and_reset(
        mut slf: PyRefMut<'_, Self>,
        keys: Py<PyBytes>,
        py: Python<'_>,
    ) -> PyResult<Iter> {
        let reader = Py::new(py, slf.clone())?;
        slf.inner.clear();
        Ok(Iter {
            reader,
            keys,
            idx: 0,
        })
    }
}

#[pyclass]
#[derive(Debug)]
struct Iter {
    reader: Py<Reader>,
    keys: Py<PyBytes>,
    idx: usize,
}

#[pymethods]
impl Iter {
    #[expect(clippy::self_named_constructors)]
    fn __iter__(slf: PyRef<'_, Self>) -> PyRef<'_, Self> {
        slf
    }

    fn __next__(mut slf: PyRefMut<'_, Self>) -> PyResult<Option<Py<PyAny>>> {
        let bytes = slf.keys.bind(slf.py()).as_bytes();
        match bytes.get(slf.idx) {
            Some(&b) => {
                slf.idx += 1;
                let py = slf.py();
                let reader = slf.reader.bind(py);
                let reader_ref = reader.try_borrow()?;
                let res = reader_ref
                    .inner
                    .get(&b)
                    .map(|s| PyString::new(py, s).into());
                Ok(res)
            }
            None => Ok(None),
        }
    }
}

fn reader() -> Reader {
    let reader = [(1, "a"), (2, "b"), (3, "c"), (4, "d"), (5, "e")];
    Reader {
        inner: reader.iter().map(|(k, v)| (*k, (*v).to_string())).collect(),
    }
}

#[test]
fn test_nested_iter() {
    Python::attach(|py| {
        let reader = reader().into_pyobject(py).unwrap();
        py_assert!(
            py,
            reader,
            "list(reader.get_iter(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
        );
    });
}

#[test]
fn test_clone_ref() {
    Python::attach(|py| {
        let reader = reader().into_pyobject(py).unwrap();
        py_assert!(py, reader, "reader == reader.clone_ref()");
        py_assert!(py, reader, "reader == reader.clone_ref_with_py()");
    });
}

#[test]
fn test_nested_iter_reset() {
    Python::attach(|py| {
        let reader = Bound::new(py, reader()).unwrap();
        py_assert!(
            py,
            reader,
            "list(reader.get_iter_and_reset(bytes([3, 5, 2]))) == ['c', 'e', 'b']"
        );
        let reader_ref = reader.borrow();
        assert!(reader_ref.inner.is_empty());
    });
}